题目:
Description
The Association of Chess Monsters (ACM) is planning their annual team match up against the rest of the world. The match will be on 30 boards, with 15 players playing white and 15 players playing black. ACM has many players to choose from, and they try to pick the best team they can. The ability of each player for playing white is measured on a scale from 1 to 100 and the same for playing black. During the match a player can play white or black but not both. The value of a team is the total of players' abilities to play white for players designated to play white and players' abilities to play black for players designated to play black. ACM wants to pick up a team with the highest total value.
Input
Input consists of a sequence of lines giving players' abilities. Each line gives the abilities of a single player by two integer numbers separated by a single space. The first number is the player's ability to play white and the second is the player's ability to play black. There will be no less than 30 and no
more than 1000 lines on input.
Output
Output a single line containing an integer number giving the value of the best chess team that ACM can assemble.
Sample Input
87 84
66 78
86 94
93 87
72 100
78 63
60 91
77 64
77 91
87 73
69 62
80 68
81 83
74 63
86 68
53 80
59 73
68 70
57 94
93 62
74 80
70 72
88 85
75 99
71 66
77 64
81 92
74 57
71 63
82 97
76 56
Sample Output
2506
题意:
从一群人中挑选30名队员,其中15人持黑15人持白,每个人只能持一种,而且每个人持不同棋的能力值是不一样的。现在给你这一群人的持黑和持白的能力值,让你找出一种选拔方案,使得总能力值最大。
分析:
这是一道非常经典的dp问题,所以,我们按照dp的思考方式来想这道题。
首先要找到状态,这是核心问题。通过题目我们不难发现,如果把问题缩小一点的话,其实可以变为三个部分,从多少人中选,选
多少人持白,选多少人持黑。而这三者之间是可以相对而言独立的,因此,dp的状态也就可以分为三个维度,具体可表示为:
dp(i,j,k)——前i个人中选择j个人持白,k个人持黑的方案中最大的能力值是多少。
第二步就是根据状态写递推方程了,找到正确的状态后写出方程并不算难,当前状态下的最佳方案是从三个方案中择优的,即不选
当前这个人,选这个人持白,选这个人持黑。马上就可以得到dp(i,j,k)=max(dp(i-1,j,k),dp(i-1,j-1,k)+a[i],dp(i-1,j,k-1)+b[i]).
第三步划分边界最容易被忽视,这次就是没有考虑好边界的问题草草处理导致一直wrong下去。(好吧可能也是由于我太笨)。本处
的边界主要问题在于当j和k等于0时的处理,具体的方案不再赘述,读者可自行思考或看下面的代码。
反思:
这道题找状态我的确费了挺大劲,刚学dp没多久的确是自己能力还是不够,需要多练类似的问题。另外在边界问题的细节处理上还
是有些大意了。同时,写完本题后我在想,其实这题完全没必要写成三维的,可以仿照背包问题对它进行空间优化,降维至二维。
#include <iostream>
#include <cmath>
#include <cstring>
#include <stdio.h>
using namespace std;
int a[1005];//记录每个人的白方得分
int b[1005];//记录每个人的黑方得分
int dp[1005][17][17];
int main()
{
int i =1;
memset(dp,0,sizeof(dp));
// freopen("in.txt","r",stdin);
while(scanf("%d%d",&a[i],&b[i])!=EOF)
{
for(int j=0;j <=i&&j<=15;j++)
{
for(int k =0;k<=i&&k<=15;k++)
{
//此处j和k等于0的边界要注意
if(j==0&&k==0)
continue;
else if(j==0)
{
dp[i][j][k]=max(dp[i-1][j][k],dp[i-1][j][k-1]+b[i]);
continue;
}
else if(k==0)
{
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+a[i]);
continue;
}
if(j+k<=i)
dp[i][j][k]=max(dp[i-1][j][k],max(dp[i-1][j-1][k]+a[i],dp[i-1][j][k-1]+b[i]));
// cout << dp[i][j][k]<< " ";
}
}
i++;
}
cout << dp[i-1][15][15] << endl;
}