POJ - 2184 Cow Exhibition
阿新 • • 發佈:2018-06-10
兩個 註意 ani bug ima #define src size http
題目大意:
每只牛有智慧數值和滑稽值,你的目標是,從n之中挑選x只(可以是0)使得智慧之和和滑稽值和(兩個都不能為 0)的總和最大
分析:
01背包(帶負權)。很顯然我們能選擇智慧值做背包容量,來當01背包來做(也可以把滑稽值當背包容量),但 是我們要註意到不管是智慧值還是滑稽值都可能使負的,所以我們要分成兩種情況。 1.s[i]>=0,就使普通的01背包,從後往前dp 2.s[i]<0,從前往後進行dp。 第二種從前往後的原因:因為智慧值為負值,所以當前這個背包容量的價值是由j-s[i](例:s[i]=-1,j=3,則 dp[3]=max(dp[3],dp[3-(-1)]+f[i]))轉移過來的,所以使從前往後dp。
code:
#define debug #include<stdio.h> #include<math.h> #include<cmath> #include<queue> #include<stack> #include<string> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<functional> #include<iomanip> #include<map> #include<set> #define pb push_back #define dbg(x) cout<<#x<<" = "<<(x)<<endl; #define lson l,m,rt<<1 #define cmm(x) cout<<"("<<(x)<<")"; #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; const int maxn=1e5; const int INF=0x3f3f3f3f; const ll inf=0x7fffff; const int mod=1e9+7; const int MOD=10007; //---- //define int dp[maxn]; int s[maxn],f[maxn]; //solve void solve() { int n,tots=0; cin>>n; for(int i=0; i<n; i++) { cin>>s[i]>>f[i]; if(s[i]>=0)tots+=s[i];//偏移量(除負數外的最大背包容量) } memset(dp,-INF,sizeof(dp)); dp[tots]=0;//因為背包容量不能為負值,所以加上偏移量,從tots開始(相當於原來01背包中的dp[0]=0) for(int i=0; i<n; i++) { if(s[i]>=0) for(int j=2*tots; j>=s[i]; j--)dp[j]=max(dp[j],dp[j-s[i]]+f[i]); else for(int j=0; j<=2*tots+s[i]; j++)dp[j]=max(dp[j],dp[j-s[i]]+f[i]); } int ans=0; for(int i=tots; i<=2*tots; i++) if(dp[i]>0)ans=max(dp[i]+i-tots,ans); cout<<ans<<endl; } int main() { ios_base::sync_with_stdio(0); #ifdef debug freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif cin.tie(0); cout.tie(0); solve(); return 0; }
POJ - 2184 Cow Exhibition