当前位置:   article > 正文

Codeforces,Kefa and Dishes,状态压缩DP_kefa and pack伪代码

kefa and pack伪代码

题意:

给定n个物品,每个物品都有一个满意度v,现在从n个物品中选取m个,选的过程中有几个规则,它们是基于选择顺序给出的规则,例如:选择的过程中a和b相邻,且a在b的前面,则满意度增加c,现在给出了k个这样的规则。问你根据这些规则,从n个物品中选取m个的最大满意度是多少。

范围:

0<=n,m<=18,k<=n*(n-1),v<=10^9

分析:

通过n和m的范围,很容易想到对状态进行压缩。

我的初始错误解法:dp[mask]表示当前的状态,然后遍历n个物品,若i不再mask中,则加入;并且遍历与i有关的规则,若i,j都不在,在加入i,j。

上述状态表示不知道当前结尾的物品是什么,反应的信息不够,最终任何两个相邻的物品,都要根据规则来进行加分,但是上述状态是没法做到这样的。

所以改变状态表示dp[mask][i]表示当前物品状态为mask,且结尾的物品为i,这样就可以根据物品i和规则来进行转移了。

注意:因为满意度可以为0,所以初始化dp[][]的时候,要初始化为-1,初始化为0是错的。

具体代码:

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<vector>
  6. #include<queue>
  7. #include<cmath>
  8. #include<set>
  9. using namespace std;
  10. #define N 300010
  11. typedef long long LL;
  12. #define aa frist
  13. #define bb second
  14. int n,m,k;
  15. LL a[20],dp[N][19];
  16. //vector<pair<int,LL> > rule[20];
  17. int cal(int v)
  18. {
  19. int num=0;
  20. while(v>0)
  21. {
  22. if(v&1) num++;
  23. v/=2;
  24. }
  25. return num;
  26. }
  27. LL rs[20][20];
  28. int main()
  29. {
  30. while(scanf("%d%d%d",&n,&m,&k)!=EOF) //
  31. {
  32. for(int i=0; i<n; i++)
  33. {
  34. scanf("%I64d",&a[i]);
  35. // rule[i].clear();
  36. }
  37. memset(rs,0,sizeof(rs));
  38. for(int i=0; i<k; i++)
  39. {
  40. int x,y;
  41. LL c;
  42. scanf("%d%d%I64d",&x,&y,&c);
  43. x--;
  44. y--;
  45. // rule[x].push_back(make_pair(y,c));
  46. rs[x][y]=c;
  47. }
  48. memset(dp,-1,sizeof(dp)); //Initialize dp as -1, but as 0 is wrongAnswer.
  49. LL ans=0;
  50. int msk=(1<<n);
  51. for(int i=0; i<msk; i++)
  52. {
  53. for(int j=0; j<n; j++)
  54. {
  55. int now=1<<j;
  56. if(i==0)
  57. {
  58. dp[i|now][j]=a[j];
  59. // printf("i=%d p=%d dp[%d][%d]=%d\n",i,j,i,j,dp[i|now][j]);
  60. // continue;
  61. }
  62. else if(dp[i][j]!=-1)
  63. {
  64. for(int p=0; p<n; p++)
  65. {
  66. now=1<<p;
  67. if(i&now) continue;
  68. else
  69. {
  70. dp[i|now][p]=max(dp[i|now][p],dp[i][j]+a[p]+rs[j][p]);
  71. // printf("i=%d p=%d dp[%d][%d]=%d\n",i,p,i|now,p,dp[i|now][p]);
  72. }
  73. }
  74. // int sz=rule[j].size();
  75. // for(int p=0; p<sz; p++)
  76. // {
  77. // int t=rule[j][p].first;
  78. // int v=rule[j][p].second;
  79. // // now=1<<t;
  80. // // printf("%d %d %d\n",i,1<<j,1<<t);
  81. // now=1<<t;
  82. // if(i&now) continue;
  83. // else
  84. // {
  85. // dp[i|now][t]=max(dp[i|now][t],dp[i][j]+a[j]+a[t]+v);
  86. // // printf("i=%d dp[%d]=%d\n",i,state,dp[state]);
  87. // }
  88. // }
  89. }
  90. if(cal(i)==m) ans=max(ans,dp[i][j]);
  91. }
  92. // printf("i=%d num=%d dp[%d]=%d\n",i,cal(i),i,dp[i]);
  93. }
  94. printf("%I64d\n",ans);
  95. }
  96. return 0;
  97. }
  98. /*
  99. 2 2 2
  100. 1 1
  101. 2 1 1
  102. 1 2 2
  103. 2 2 0
  104. 1 1
  105. 4 3 2
  106. 1 2 3 4
  107. 2 1 5
  108. 3 4 2
  109. */


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/72482?site
推荐阅读
相关标签
  

闽ICP备14008679号