POJ2184 - Cow Exhibition(01背包+负数处理 )

题目链接:http://poj.org/problem?id=2184

题意:给你n头奶牛,每头奶牛都有一个智商和情商,在选出的x头奶牛智商和情商和都大于等于0的情况下求智商总和与情商总和的最大值。

思路:以智商或者情商为价值,另一个为重量,就是典型的01背包问题,首先重量为正数时就是正常的01背包,但重量为负数时由于下标不能为负,我们需要增加数组长度。也就是把坐标0向正方向移动:0。。。B。。。N,0 - B 之间为负数,B - N之间为正数,dp[B]为0。然后就可以进行01背包了。最后扫一遍正数区间更新一个最大值即可。

注意:重量为负数时我们从N ~ w[ i ]进行状态转移时会覆盖掉已经更新的答案,所以应该反过来从0 ~ N+w[ i ]。还要初始化为负的最大值(类似恰好装满问题)

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define inf 0x3f3f3f3f
const int N = 2e5+8;
const int B = 1e5;
int n, dp[N], w[N], v[N];
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i = 0; i < n; i++)
            scanf("%d %d",&v[i], &w[i]);
        for(int i = 0; i < N; i++) dp[i] = -inf;
        dp[B] = 0;
        for(int i = 0; i < n; i++)
        {
            if(w[i] > 0)
            for(int j = N; j >= w[i]; j--)
                dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
            else
            for(int j = 0; j < N + w[i]; j++)
                dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
        }
        int ans = 0;
        for(int i = B; i < N; i++)
        {
            if(dp[i] > 0)
                ans = max(ans, dp[i] + i - B);
        }
        printf("%d\n",ans);
    }
}

 

你可能感兴趣的:(【优美的暴力------dp】)