dp打开思路2:POJ2533 HDU1114 HDU1260 HDU1160(水题不水)

举报
兔老大 发表于 2021/04/21 01:13:43 2021/04/21
【摘要】 题目:https://vjudge.net/contest/68966#overview POJ2533 最长上升子序列,很平常的题,但是维持单调队列+二分还是值得一贴的,O(nlogn) 关键思想:出现在单调队列里的数都在当前接收的数之前,所以找到最小的比他大的数替换即可,而替换的位置其实就相当于它的DP[i],只是已经没有记录的必要了。如果是当前最大就放到最后,cn...

题目:https://vjudge.net/contest/68966#overview

POJ2533

最长上升子序列,很平常的题,但是维持单调队列+二分还是值得一贴的,O(nlogn)

关键思想:出现在单调队列里的数都在当前接收的数之前,所以找到最小的比他大的数替换即可,而替换的位置其实就相当于它的DP[i],只是已经没有记录的必要了。如果是当前最大就放到最后,cnt++。

最后单调数组长度就是所求,并且数组内的数组成的就是最长上升序列。

 (对萌新通俗点说,一个数比你先出现,还比你大,dp值还一样,那他肯定已经没用了)


  
  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. const int maxn = 1005;
  5. int Binary_Search(int *a,int left,int right,int element)//二分标准写法,用熟
  6. {
  7. int l = left;
  8. int r = right;
  9. int mid;
  10. while(l < r)
  11. {
  12. mid = (l + r) / 2;
  13. if(a[mid] <= element) l = mid + 1;
  14. else
  15. r = mid;
  16. }
  17. return l;
  18. }
  19. int main()
  20. {
  21. int m;
  22. int i;
  23. while(cin>>m)
  24. {
  25. int t;
  26. int cnt;
  27. int a[maxn];
  28. cnt = 0;
  29. scanf("%d",&a[0]);
  30. cnt++; //一个元素插入队列
  31. //cout<<cnt<<endl;
  32. for(i=1;i<m;i++)
  33. {
  34. scanf("%d",&t);
  35. if(t > a[cnt-1])
  36. {
  37. a[cnt++] = t;
  38. }
  39. else
  40. {
  41. a[Binary_Search(a,0,cnt,t)] = t;
  42. }
  43. }
  44. printf("%d",cnt);
  45. }
  46. return 0;
  47. }

HDU1114

背包题:经典背包求最大利益,这是求最小可能利益

所以,状态转移方程是这样:dp[j] = min(dp[j],dp[j-wei[i]]+val[i]);没必要贴代码

HDU1260

递推,姑且叫一维dp吧,不难,对当前人就两种选择,自己买,或者和上一个人一起买

所以dp[i][1]=dp[i-1][0]+y[i]-x[i-1];

dp[i][0]=min(dp[i-1][0],dp[i-1][1])+x[i];

dp[i][0]表示第i个人单独买票dp[i][1]表示i个人和前面的人一起买票。和以前一道题类似。也没必要贴代码

HDU1160

也是简单变形,先按照重量排序,然后找出LIS最长上升子序列就可以了

排序,记录,回溯,操作略麻烦,而且是挺好的题,代码就贴出来。


  
  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<string.h>
  6. using namespace std;
  7. struct Mice{
  8. int w,v,id;
  9. }mice[1010];
  10. int dp[1010];
  11. int pre[1010];
  12. bool cmp(Mice a,Mice b)
  13. {
  14. return a.w>b.w;
  15. }
  16. int main()
  17. {
  18. int s=0;
  19. while(scanf("%d%d",&mice[s].w,&mice[s].v)!=EOF)
  20. {
  21. mice[s].id=s+1;
  22. s++;
  23. }
  24. sort(mice,mice+s,cmp);
  25. memset(pre,-1,sizeof(pre));
  26. for(int i=0;i<s;i++)
  27. dp[i]=1;
  28. for(int i=0;i<s;i++)
  29. for(int j=0;j<i;j++)
  30. {
  31. if(mice[j].w>mice[i].w&&mice[j].v<mice[i].v)
  32. {
  33. if(dp[i]<dp[j]+1)
  34. {
  35. dp[i]=dp[j]+1;
  36. pre[i]=j;//注意记录
  37. }
  38. }
  39. }
  40. int ans=0;
  41. int p;
  42. for(int i=0;i<s;i++)
  43. {
  44. if(dp[i]>ans)
  45. {
  46. ans=dp[i];
  47. p=i;
  48. }
  49. }
  50. printf("%d\n",dp[p]);
  51. while(p!=-1)//回溯
  52. {
  53. printf("%d\n",mice[p].id);
  54. p=pre[p];
  55. }
  56. }

 

 

 

 

 

 

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/81393716

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。