题意:
给定两串数字,有正有服,求出最大和,且这个和的状态下满足任一边都不为负。
思路:
dp。
说是背包,但是其实完全不懂背包的也可以做出来。
本质就是用dp数组来记录状态,然后依次增加状态和更新而已。。
值得注意的就是对负值平移成非负的。
- #include<iostream>
- #include<stdio.h>
- #include<string.h>
- #include<algorithm>
- #define Max(a,b) ((a)>(b)?(a):(b))
- #define Min(a,b) ((a)<(b)?(a):(b))
- using namespace std;
- const int N=105;
- const int ost=100000;
- const int inf=(1<<30);
- int n,m;
- int d[2*ost+5];
- struct Node
- {
- int s,f;
- }a[N];
- void solve()
- {
- memset(d,0,sizeof(d));
- d[ost]=ost;
- int l=ost,r=ost;
- for(int i=1;i<=n;i++)
- {
- int s=a[i].s;
- int f=a[i].f;
- if(s>0)
- {
- for(int j=r;j>=l;j--)
- {
- if(d[j])
- {
- d[j+s]=Max(d[j]+f,d[j+s]);
- r=Max(r,j+s);
- }
- }
- }
- else
- {
- for(int j=l;j<=r;j++)
- {
- if(d[j])
- {
- d[j+s]=Max(d[j]+f,d[j+s]);
- l=Min(j+s,l);
- }
- }
- }
- }
- int ans=0;
- for(int i=ost;i<=r;i++)
- if(d[i]&&d[i]>=ost)
- {
- ans=Max(ans,d[i]+i-2*ost);
- }
- printf("%d\n",ans);
- }
- int main()
- {
- scanf("%d",&n);
- for(int i=1;i<=n;i++)
- {
- scanf("%d%d",&a[i].s,&a[i].f);
- }
- solve();
- return 0;
- }