题意: 小 ho 和小 hi 在玩游戏,给定一个数字串,每人每次从该串的开头或结尾选取一个数,直到选完为止,最后选取数字之和较大的那个人获胜。其中小 ho 先手。求小 ho 能获得的最大分数。
思路: 由样例可以看出,每次选取首尾中较大的数的这个贪心策略是错误的。
设 f[i][i] 表示对于 A[i,...,j] 数字串的先手能够获得的最大分数。
当 i==j 时,则 f[i][i]=A[i];
当 i < j 时,则先手可能选择 A[i] 或者 A[j]。如果先手选择 A[i],则后手得到的数字串是 A[i+1,...,j],对应的后手能从该数字串中得到 f[i+1][j] 的最大分数。则后手肯定会按照能够获得最大分数的决策进行下一步选择,则此时先手能够获得的最大分数就是 ∑k=i−>jA[k]−f[i+1][j]。如果先手选择 A[j] 同理。
所以最终 f[i][j]=max(∑k=i−>jA[k]−f[i+1][j],∑k=i−>jA[k]−f[i][j−1])。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
int N;
int A[1010];
int f[1010][1010];
int s[1010][1010];
int main()
{
//freopen("in.txt", "r", stdin);
while(scanf("%d", &N) == 1){
for(int i=0; i<N; i++){
scanf("%d", &A[i]);
}
for(int i=0; i<N; i++){
for(int j=i; j<N; j++){
if(i == j) s[i][j] = A[i];
else{
s[i][j] = A[j]+s[i][j-1];
}
}
}
for(int i=0; i<N; i++){
f[i][i] = A[i];
}
for(int len=2; len<=N; len++){
for(int i=0; i+len-1<N; i++){
int j = i+len-1;
f[i][j] = s[i][j]-min(f[i+1][j], f[i][j-1]);
}
}
printf("%d\n", f[0][N-1]);
}
return 0;
}

本文介绍了一种两人游戏中的最优策略问题,通过动态规划的方法来解决数字串游戏中如何选择数字以获得最大分数的问题。详细解释了状态转移方程,并给出了完整的代码实现。
5987

被折叠的 条评论
为什么被折叠?



