poj 2184
地址:http://poj.org/problem?id=2184
题意:有很多羊,每只羊有一个幽默度和智商,要选出一些羊,智商加幽默度总和最大,其中智商总和和幽默度总和都不能是负数。
mark:变种的01背包,可以把幽默度看成体积,智商看成价值,那么就转换成求体积和价值都为正值的最大值的01背包了。
由于有负数,所以可以每个体积+1000,然后开一个数组记录用该体积得到最大值时用了多少个1000.
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <iostream> #include <algorithm> #include <map> #define LL long long using namespace std; const int N = 110; const int M = 200010; const int NN = 1000; const int INF = 10000000; int w[N],v[N],sum; int dp[M], cnt[M]; int main() { // freopen("out1.txt", "w", stdout); int n,ans; int i,j; while(~scanf("%d", &n)) { sum = 0; for(i = 1; i <= n; i++) { scanf("%d%d", v+i, w+i); if(w[i] <= 0 && v[i] <= 0) {i--,n--; continue;} v[i] += 1000; sum += v[i]; } for(i = 1; i <= sum; dp[i++] = -INF); dp[0] = 0; memset(cnt, 0, sizeof(cnt)); for(i = 1; i <= n; i++) for(int j = sum; j >= v[i]; j--) if(dp[j-v[i]]+w[i]-(cnt[j-v[i]]+1)*NN > dp[j]-cnt[j]*NN) { dp[j] = dp[j-v[i]]+w[i]; cnt[j] = cnt[j-v[i]]+1; } ans = 0; for(i = 0; i <= sum; i++) if(dp[i] >= 0 && i-cnt[i]*NN >= 0) ans = max(ans, dp[i]+i-cnt[i]*NN); printf("%d\n", ans); } return 0; }
posted on 2012-09-19 18:39 andre_joy 阅读(1242) 评论(0) 编辑 收藏 举报