Time Limit: 1000MS |
|
Memory Limit: 65536K |
Total Submissions: 10929 |
|
Accepted: 4338 |
Description
Input
Output
Sample Input
5
-5 7
8 -6
6 -3
2 1
-8 -5
Sample Output
8
Hint
//dp解法:01背包变形 #include<cstdio> #include<cstring> #include<algorithm> #define INF 0x3f3f3f using namespace std; int dp[200050]; int s[110],f[110]; int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;++i) scanf("%d%d",&s[i],&f[i]); for(i=0;i<=200000;++i) dp[i]=-INF; dp[100000]=0; for(i=0;i<n;++i) { if(s[i]<0&&f[i]<0) continue; if(s[i]>0) { for(j=200000;j>=s[i];--j) dp[j]=max(dp[j],dp[j-s[i]]+f[i]); } else//负数需要反过来 { for(j=s[i];j<=200000+s[i];j++) dp[j]=max(dp[j],dp[j-s[i]]+f[i]); } } int ans=-INF; for(i=100000;i<=200000;++i)//因为区间100000~200000才是表示的整数,那么此时的i就是之前背包中的s[i],如果此时dp[i]也就是f[i]大于等于0的话,我们再加上s[i](此时为i),然后减去作为界限的100000,就可以得到答案 if(dp[i]>=0) ans=max(ans,dp[i]+i-100000); printf("%d\n",ans); } return 0; }
//dfs+剪枝解法 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node { int s,f; }cow[110]; int n,sum_s,sum_f,ans; int sum[110]; int cmp(node a,node b) { return a.s+a.f>b.s+b.f; } void dfs(int x) { if(x==n) { if(sum_s>=0&&sum_f>=0) ans=max(sum_s+sum_f,ans);//更新最大值 return ; } if(cow[x].s+cow[x].f<0&&sum_s+sum_f<ans) return ; if(sum_s+sum_f+sum[x]<=ans) return ; sum_s+=cow[x].s; sum_f+=cow[x].f; dfs(x+1); sum_s-=cow[x].s; sum_f-=cow[x].f; dfs(x+1); } int main() { int i; while(scanf("%d",&n)!=EOF) { sum_s=0; sum_f=0; ans=0; for(i=0;i<n;++i) { scanf("%d%d",&cow[i].s,&cow[i].f); if(cow[i].s>=0&&cow[i].f>=0)//都是正数,直接取用 { sum_s+=cow[i].s; sum_f+=cow[i].f; i--; n--; } else if(cow[i].s<0&&cow[i].f<0)//两个性质都是负数,直接不计入 { i--; n--; continue; } } ans=sum_s+sum_f; sort(cow,cow+n,cmp); memset(sum,0,sizeof(sum)); for(i=n-1;i>=0;--i) { if(cow[i].s+cow[i].f<=0) sum[i]=0; else sum[i]=sum[i+1]+cow[i].s+cow[i].f;//记录每个牛前面牛的总值 } dfs(0); printf("%d\n",ans); } return 0; }