[关闭]
@Pinetrie 2019-02-26T17:30:48.000000Z 字数 2008 阅读 956

I - Crazy Shopping ZOJ - 3524

题意

在一个DAG图上有N个点,每个点有重量为v[i]的价值为w[i]的物品无限个,背包容量为W,起点为X。背有重量为K的物品走dis的路程,消耗k*dis的体力。求达到最大价值时消耗的最小体力是多少。

题解

明显是一个完全背包的问题,但是不能直接按顺序更新点。DAG图于是需要先拓扑排序,再进行完全背包的dp。dp的时候需要同时更新价值和体力。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 1010;
  4. int N,M,W,X,tot,v[maxn],w[maxn],du[maxn],topus[maxn],vis[maxn];
  5. struct node
  6. {
  7. int net,dis;
  8. };
  9. vector<node>e[maxn];
  10. struct ans
  11. {
  12. int val,power;
  13. }dp[maxn][maxn * 2];
  14. void topusort()
  15. {
  16. queue<int>Q;
  17. for(int i = 1;i <= N;i++)
  18. {
  19. if(du[i] == 0)
  20. Q.push(i);
  21. }
  22. tot = 0;
  23. while(!Q.empty())
  24. {
  25. int u = Q.front();
  26. Q.pop();
  27. topus[++tot] = u;
  28. for(int i = 0;i < e[u].size();i++)
  29. {
  30. int to = e[u][i].net;
  31. du[to]--;
  32. if(du[to] == 0) Q.push(to);
  33. }
  34. }
  35. }
  36. void slove()
  37. {
  38. for(int i = 0;i <= W;i++)
  39. {
  40. dp[X][i].power = 0;
  41. if(i >= v[X]) dp[X][i].val = max(dp[X][i].val,dp[X][i - v[X]].val + w[X]);
  42. }
  43. vis[X] = 1;
  44. for(int i = 1;i <= N;i++)
  45. {
  46. int u = topus[i];
  47. if(!vis[u]) continue;
  48. for(int j = 0;j < e[u].size();j++)
  49. {
  50. int to = e[u][j].net;
  51. int dis = e[u][j].dis;
  52. vis[to] = 1;
  53. for(int k = 0;k <= W;k++)
  54. {
  55. if(dp[u][k].val > dp[to][k].val)
  56. {
  57. dp[to][k].val = dp[u][k].val;
  58. dp[to][k].power = dp[u][k].power + dis * k;
  59. }
  60. else if(dp[u][k].val == dp[to][k].val)
  61. {
  62. if(dp[to][k].power >= 0) dp[to][k].power = min(dp[to][k].power,dp[u][k].power + dis * k);
  63. else dp[to][k].power = dp[u][k].power + dis * k;
  64. }
  65. }
  66. for(int k = v[to];k <= W;k++)
  67. {
  68. if(dp[to][k].val < dp[to][k - v[to]].val + w[to])
  69. {
  70. dp[to][k].val = dp[to][k - v[to]].val + w[to];
  71. dp[to][k].power = dp[to][k - v[to]].power;
  72. }
  73. else if(dp[to][k].val == dp[to][k - v[to]].val + w[to] && dp[to][k].power > dp[to][k - v[to]].power)
  74. {
  75. dp[to][k].power = dp[to][k - v[to]].power;
  76. }
  77. }
  78. }
  79. }
  80. }
  81. void init()
  82. {
  83. for(int i = 0;i <= N;i++)
  84. {
  85. e[i].clear();
  86. du[i] = 0;
  87. vis[i] = 0;
  88. for(int j = 0;j <= W;j++)
  89. {
  90. dp[i][j].power = -1;
  91. dp[i][j].val = 0;
  92. }
  93. }
  94. }
  95. int main()
  96. {
  97. while(scanf("%d %d %d %d",&N,&M,&W,&X) != EOF)
  98. {
  99. init();
  100. for(int i = 1; i <= N; i++)
  101. scanf("%d %d",&v[i],&w[i]);
  102. for(int i = 1; i <= M; i++)
  103. {
  104. int a,b,c;
  105. scanf("%d %d %d",&a,&b,&c);
  106. node x;
  107. x.net = b,x.dis = c;
  108. e[a].push_back(x);
  109. du[b]++;
  110. }
  111. topusort();
  112. slove();
  113. int ans1,ans2;
  114. ans1 = 0;
  115. ans2 = 1e9;
  116. for(int i = 1; i <= N; i++)
  117. {
  118. for(int j = 0; j <= W; j++)
  119. {
  120. if(dp[i][j].val > ans1)
  121. {
  122. ans1 = dp[i][j].val;
  123. ans2 = dp[i][j].power;
  124. }
  125. else if(dp[i][j].val == ans1 && dp[i][j].power < ans2)
  126. {
  127. ans2 = dp[i][j].power;
  128. }
  129. }
  130. }
  131. printf("%d\n",ans2);
  132. }
  133. return 0;
  134. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注