POJ 1742 Coins ( 单调队列解法 )

举报
Linux猿 发表于 2021/08/04 23:49:09 2021/08/04
【摘要】 题目链接~~> 做题感悟:第一次做的时候用的二进制优化,但是没注意到是险过,so也没去看单调队列的解法。 解题思路:                  如果你做过单调队列的题,或者看过相关的博客就好理解这题了,博客。再加上这题体积与价值相等那么就更好做了。只有 j %v[ ...

题目链接~~>

做题感悟:第一次做的时候用的二进制优化,但是没注意到是险过,so也没去看单调队列的解法。

解题思路:

                 如果你做过单调队列的题,或者看过相关的博客就好理解这题了,博客。再加上这题体积与价值相等那么就更好做了。只有 j %v[ i ] 余数相同的才可以同时处理(j 指的是某个体积的值),在计算某个数的时候,只要计算前面的相同的余数中(在个数限制内)是否有 true(有放满的) 就可以了。

代码:


  
  1. #include<iostream>
  2. #include<sstream>
  3. #include<map>
  4. #include<cmath>
  5. #include<fstream>
  6. #include<queue>
  7. #include<vector>
  8. #include<sstream>
  9. #include<cstring>
  10. #include<cstdio>
  11. #include<stack>
  12. #include<bitset>
  13. #include<ctime>
  14. #include<string>
  15. #include<cctype>
  16. #include<iomanip>
  17. #include<algorithm>
  18. using namespace std ;
  19. #define INT long long int
  20. #define L(x) (x * 2)
  21. #define R(x) (x * 2 + 1)
  22. const int INF = 0x3f3f3f3f ;
  23. const double esp = 0.0000000001 ;
  24. const double PI = acos(-1.0) ;
  25. const int mod = 1000000007 ;
  26. const int MY = (1<<5) + 5 ;
  27. const int MX = 100010 + 5 ;
  28. int n ,W ,ans ;
  29. int v[MX] ,num[MX] ;
  30. bool deq[MX] ,dp[MX] ;
  31. void input()
  32. {
  33. memset(dp ,false ,sizeof(dp)) ;
  34. for(int i = 1 ;i <= n ; ++i)
  35. scanf("%d" ,&v[i]) ;
  36. for(int i = 1 ;i <= n ; ++i)
  37. scanf("%d" ,&num[i]) ;
  38. }
  39. void DP(int v ,int num)
  40. {
  41. if(!num || !v) return ;
  42. if(num == 1) // 01 背包
  43. {
  44. for(int i = W ;i >= v ; --i)
  45. if(!dp[i] && dp[i-v])
  46. dp[i] = true ,ans++ ;
  47. }
  48. else if(num * v >= W) // 完全背包
  49. {
  50. for(int i = v ;i <= W ; ++i)
  51. if(!dp[i] && dp[i-v])
  52. dp[i] = true ,ans++ ;
  53. }
  54. else
  55. {
  56. num = min(num ,W/v) ;
  57. for(int a = 0 ;a < v ; ++a) // 相同余数一块处理
  58. {
  59. int front =0 ,end = 0 ,sum = 0 ;
  60. for(int j = a ;j <= W ; j += v)
  61. {
  62. if(end - front-1 == num) // 去除过时元素 ,因为最多选择num[i] 个
  63. sum -= deq[front++] ;
  64. deq[end++] = dp[j] ; // 存入
  65. sum += dp[j] ;
  66. if(!dp[j] && sum)
  67. dp[j] = true ,ans++ ;
  68. }
  69. }
  70. }
  71. }
  72. int main()
  73. {
  74. //freopen("input.txt" ,"r" ,stdin) ;
  75. while(scanf("%d%d" ,&n ,&W) ,n+W)
  76. {
  77. input() ;
  78. dp[0] = true ;
  79. ans = 0 ;
  80. for(int i = 1 ;i <= n ; ++i)
  81. DP(v[i] ,num[i]) ;
  82. printf("%d\n" ,ans) ;
  83. }
  84. return 0 ;
  85. }


文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/40947189

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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