试题描述:
小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]);
}