试题描述:
小a和小b玩一个游戏,有n张卡牌,每张上面有两个正整数x,y。
取一张牌时,个人积分增加x,团队积分增加y。
求小a,小b各取若干张牌,使得他们的个人积分相等。
输入:
第一行一个整数n。
接下来n行,每行两个整数x,y,用空格隔开。
输出:
一行一个整数
表示小a的积分和小b的积分相等的时候,团队积分的最大值。
输入示例:
4
3 1
2 2
1 4
1 4
输出示例:
10
其他:
对于100%的数据,0<n<=100,1<x<=1e3,0<y<=1e6。
明显的dp,不能暴力枚举。
和0-1背包十分相似。
也是取和不取之间的关系。
注意:在两人不能为同一值时我们就要输出-1;
所以我们就可以把dp这个数组全部置为-1;
但是我们为了防止越界,所以我们要将一个很大的数组定为0.
这也就是我们之后的答案了(因为到了那里一定会有答案);
再说dp这个二维数组。dp[i][j]的i表示发到了第几张牌,j表示第一个人的积分。
在第二个人取牌时,我们就直接在j上减去一个x[i].就可以了,当他们一样是,j=0了
#include<iostream> #include<cstring> #include<cmath> #include<cstdio> using namespace std; int n,m,dp[300][200000],x[100000],y[100000]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&x[i],&y[i]); } memset(dp,-1,sizeof(dp)); dp[0][100000]=0; for(int i=1;i<=n;i++) { for(int j=20000;j<=200000;j++) { dp[i][j]=max(dp[i-1][j+x[i]],dp[i-1][j-x[i]]); if(dp[i][j]!=-1)dp[i][j]+=y[i]; if(dp[i][j]<dp[i-1][j])dp[i][j]=dp[i-1][j]; } } printf("%d",dp[n][100000]); }