POJ-2184 Cow Exhibition 【动态规划DP+01背包变换】

版权声明:本文为博主原创文章,转载请注明出处( • ̀ω•́ )✧ https://blog.csdn.net/wangws_sb/article/details/83718435

题目传送门

题目:共有N头牛,接下来N行是每头牛的智商和情商,从这些牛中任意选取若干头牛,使得牛的智商和+情商和最大,同时智商和(TS),情商和(TF)都不小于0。

题解:以智商作为容量,求前i头牛在智商为j的情况下的最大情商 。因为有负数,所以容量扩大100000,修改dp数组的起始位置为mid, 1—mid 为处理负数的区间 mid—N为处理正数的区间。初始化dp时,因为有负数,所以初始化为一个非常小的负数,起始点dp[mid]=0。dp[i][j]优化掉第i维,然后套01背包。正负数时背包不同。情商和TF通过dp数组可以得到,智商和TS通过dp数组的下标和起始点对比得到(TS[i]=i-mid)。

AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define inf 99999999
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e5+7;
const int N=200005;
const int mid=100000;
int n;
int w[105],v[105],dp[N];
int main()
{
    io;
    cin>>n;
    for(int i=1; i<=n; i++)
        cin>>w[i]>>v[i];
    for(int i=0; i<=N; i++)//初始化dp,因为有负数,所以初始化为一个非常小的负数
        dp[i]=-inf;
    dp[mid]=0;//起始点初始化为0
    for(int i=1; i<=n; i++)
    {
        if(w[i]>0)
        {
            for(int j=N-1; 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=mid; i<=N; i++)//从智商和为0开始
    {
        if(dp[i]>=0)//情商和大于0
            ans=max(ans,dp[i]+i-mid);//dp数组存的是TF,通过i-mid计算TS
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/wangws_sb/article/details/83718435