andre_joy

导航

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编辑  收藏  举报