【问题描述】
小a和小b玩一个游戏,有n张卡牌,每张上面有两个正整数x,y。
取一张牌时,个人积分增加x,团队积分增加y。
求小a,小b各取若干张牌,使得他们的个人积分相等。
【输入】
第一行n
接下来n行,每行两个整数x,y,用空格隔开。
【输出】
一行一个整数
表示小a的积分和小b的积分相等的时候,团队积分的最大值。
题解:这道题的dp方程是dp[i][j]=max(dp[i][j+a[i]*k],dp[i-1][j]);(k>=-1,k<=1)。因为k=-1时给b,k=1时给a,k=0时谁都不给,dp[i][j]表示取到第i个牌,a,b状态为j,j<100000时a小,j>100000时b小,j=100000时一样,初值:memeset(dp,-999999,sizeof(dp));dp[0][100000]=0;
以下是代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int dp[105][200005]; int a[105],b[105]; int sum[105]; int main() { //freopen("card.in","r",stdin); //freopen("card.out","w",stdout); int n; cin>>n; for(int i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); sum[i]=sum[i-1]+a[i]; } memset(dp,-999999,sizeof(dp)); dp[0][100000]=0; for(int i=1;i<=n;i++) { for(int j=100000-sum[i];j<=100000+sum[i];j++) { for(int k=-1;k<=1;k++) { if(k!=0) { dp[i][j+k*a[i]]=max(dp[i-1][j]+b[i],dp[i][j+k*a[i]]); } else { dp[i][j]=max(dp[i][j],dp[i-1][j]); } } } } cout<<dp[n][100000]; return 0; }