您的位置:首页 > 其它

HDU_3496 Watch The Movie (背包)

2011-12-06 17:30 344 查看
  这是道好题。至少我错了不下10次。dp的两个重点:转移方程+初始化。偶敢保证,偶的转移方程绝对没问题。可是初始化上wa到shi了。昨天想了整整一晚上,跟经典01背包那么像,加上一个容器就写不出来了。然后问鱼神,鱼神说这题的数据人畜无害,哄小盆友的。我了个去!然后问他思路,说设f[i][j][k],表示前i个中挑j个占容量是k时的最大value,然后就没有然后了。。。

  我自己就在那列各种状态,各种推导。思路还是很模糊,后来又好几次问鱼神。甚至有几次让我问的直接不鸟我了。T_T悲摧的人生啊。。。

  后来推出:

  f[i][j][k] = max(f[i-1][j][k], f[i-1][j-1][k - c[i]] + w[i]);

  转移方程出来我以为这题差不多就过了,可恨的是这是一个满背包。01背包时,满背包处理是f[1..n][0] = 0, 其余都等于-∞,可是这按照这个思路把f[1..N][0][1..L]初始化成0,其余是-∞却不对。wa了有十几次。最后根据背包九讲里简化01背包空间复杂度的方法把三维数组化成二维的。f[j][k]表示挑满j个物品占容量为k时的最大value。

  f[j][k] = max(f[j][k], f[j-1][k-c[i]] + w[i]) (类比经典01背包简化, f[i] = max(f[i], f[i-c[i]] + w[i])).

  然后通过经典01背包简化过后的写法:

for i=1..N
for v=V..0
f[v]=max{f[v],f[v-c[i]]+w[i]};


  因为f[i][v]是从f[i-1][v-c[i]] + w[i] 推出的。如果v = 0...V的话就成了。f[i][v] = f[i][v-c[i]]。

这题的转移过程就是:

for(i = 1; i <= n; i++) {
for(j = m; j - 1 >= 0; j--) {
for(k = l; k > 0 && k - c[i] >= 0; k--) {
f[j][k] = max(f[j][k], f[j-1][k-c[i]] + w[i]);
}
}
}


  初始化跟上面三维数组写法一样。f[0][1...L] = 0, 其他都是-∞。还得加上一个限制,当前一个不能背满时,不转移。

for(k = l; k > 0 && k - c[i] >= 0; k--) {
if(f[j-1][k-c[i]] != inf)
f[j][k] = max(f[j][k], f[j-1][k-c[i]] + w[i]);
}


My Code:

View Code

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

const int N = 107;
const int M = 1024;
const int inf = -(~0u>>2);

int f
[M];
int c
, w
;

int main() {
//freopen("data.in", "r", stdin);

int i, j, k;
int n, m, l, t;
scanf("%d", &t);
while(t--) {
scanf("%d%d%d", &n, &m, &l);
for(i = 1; i <= n; i++) {
scanf("%d%d", &c[i], &w[i]);
}
for(j = m; j >= 0; j--) {
for(k = l; k >= 0; k--)
f[j][k] = inf;
}
for(i = 0; i <= l; i++) {
f[0][i] = 0;
}
for(i = 1; i <= n; i++) {
for(j = m; j - 1 >= 0; j--) {
for(k = l; k > 0 && k - c[i] >= 0; k--) {
if(f[j-1][k-c[i]] != inf)
f[j][k] = max(f[j][k], f[j-1][k-c[i]] + w[i]);
}
}
}
//cout << inf << endl;
if(f[m][l] == inf)    {cout << '0' << endl; continue;}
cout << f[m][l] << endl;
}
return 0;
}


ps:有人直接秒过了,Orz!不过我觉得好题应该好做。^_^。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: