1、题目类型:01背包问题扩展,DP。
2、解题思路:DP递推式:
for i=1...N
for j=left...right
DP[j]=DP[j+S[i]]+F[i]
其中 i 表示第 i 头牛,j 表示当前TS,DP[j]表示TS=j 时的FS。
3、注意事项:注重DP[i]的状态保持,其他方法TLE;用left、right 记录边界提高的遍历效率;用Flag[]标示是否可用。
4、实现方法:
#include<iostream>
using namespace std;
#define Max 9999999
#define Maxn 1001
#define Maxt 2000001
int S[Maxn],F[Maxn],DP[Maxt];
bool Flag[Maxt];
int main()
{
int n,i,j,k,right,left,sum;
for(i=0;i<Maxt;i++)
DP[i]=-Max;
k=100000;
right=left=0;
DP[k]=0;
Flag[k]=true;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>S[i]>>F[i];
if(S[i]<0 && F[i]<0)
continue;
if(S[i]<0)
{
for(j=left;j<=right;j++)
{
if(Flag[j+k]==true && DP[j+S[i]+k]<DP[j+k]+F[i])
{
DP[j+S[i]+k]=DP[j+k]+F[i];
Flag[j+S[i]+k]=true;
}
}
left+=S[i];
}
else
{
for(j=right;j>=left;j--)
{
if(Flag[j+k]==true && DP[j+S[i]+k]<DP[j+k]+F[i])
{
DP[j+S[i]+k]=DP[j+k]+F[i];
Flag[j+S[i]+k]=true;
}
}
right+=S[i];
}
}
sum=0;
for(i=right;i>=0;i--)
{
if(Flag[i+k]==true && DP[i+k]>=0 && i+DP[i+k]>sum)
sum=i+DP[i+k];
}
cout<<sum<<endl;
return 1;
}
using namespace std;
#define Max 9999999
#define Maxn 1001
#define Maxt 2000001
int S[Maxn],F[Maxn],DP[Maxt];
bool Flag[Maxt];
int main()
{
int n,i,j,k,right,left,sum;
for(i=0;i<Maxt;i++)
DP[i]=-Max;
k=100000;
right=left=0;
DP[k]=0;
Flag[k]=true;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>S[i]>>F[i];
if(S[i]<0 && F[i]<0)
continue;
if(S[i]<0)
{
for(j=left;j<=right;j++)
{
if(Flag[j+k]==true && DP[j+S[i]+k]<DP[j+k]+F[i])
{
DP[j+S[i]+k]=DP[j+k]+F[i];
Flag[j+S[i]+k]=true;
}
}
left+=S[i];
}
else
{
for(j=right;j>=left;j--)
{
if(Flag[j+k]==true && DP[j+S[i]+k]<DP[j+k]+F[i])
{
DP[j+S[i]+k]=DP[j+k]+F[i];
Flag[j+S[i]+k]=true;
}
}
right+=S[i];
}
}
sum=0;
for(i=right;i>=0;i--)
{
if(Flag[i+k]==true && DP[i+k]>=0 && i+DP[i+k]>sum)
sum=i+DP[i+k];
}
cout<<sum<<endl;
return 1;
}