1. 程式人生 > >POJ-2184 Cow Exhibition 【動態規劃DP+01揹包變換】

POJ-2184 Cow Exhibition 【動態規劃DP+01揹包變換】

題目傳送門

題目:共有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;
}