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