这是问题陈述:
这是一款双人游戏。最初在数组中有n个整数,玩家A和B有机会交替使用它们。每个玩家可以从阵列的左端或右端获取一个或多个数字,但一次不能从两端获取。在他那段时间里,他可以随心所欲地连续数字。当玩家从阵列中取出所有数字时,游戏结束。每个球员的得分是通过他所取得的数字的总和来计算的。每个玩家都试图从其他玩家获得更多积分。如果两个玩家都发挥最佳状态并且玩家A开始游戏,则玩家A获得的积分比玩家B多多少?
输入
输入包含许多案例。每个案例都以一行指定整数
的行终止n (0 < n ≤100)
,即数组中的元素数。之后,为游戏提供n
个数字。输入由n=0
。输出
对于每个测试用例,打印一个数字,表示第一个玩家在以最佳方式玩游戏后获得的最大差异。
Sample Input Output for Sample Input
4
4 -10 -20 7 7
4
1 2 3 4 10
5
4 -10 -20 7 19 12
0
这是这个问题的解决方案。
#include<stdio.h>
#include<stdlib.h>
#define maxn 103
//typedef long long bg;
typedef long bg;
bg Table[maxn][maxn];
bg Seq[maxn];
bool Flag[maxn][maxn];
bg N;
bg Sum(int l, int r) {
int i, sum = 0;
for (i = l; i <= r; i++)
sum += Seq[i];
return sum;
}
bg Recur(int L, int R) {
bg max, i, d, k;
if (L == R)
return Seq[L];
if (Flag[L][R])
return Table[L][R];
max = Sum(L, R);
d = Seq[L];
for (i = L + 1; i <= R; i++) {
k = Recur(i, R);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
d = Seq[R];
for (i = R - 1; i >= L; i--) {
k = Recur(L, i);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
Flag[L][R] = true;
Table[L][R] = max;
return max;
}
void Cal() {
bg max, i, d, k;
max = Sum(1, N);
d = Seq[1];
for (i = 2; i <= N; i++) {
k = Recur(i, N);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
d = Seq[N];
for (i = N - 1; i >= 1; i--) {
k = Recur(1, i);
if ((d - k) > max)
max = d - k;
d += Seq[i];
}
printf("%ld\n", max);
}
void Reset() {
for (int i = 1; i <= 100; i++) {
for (int j = 1; j <= 100; j++)
Flag[i][j] = false;
}
}
int main() {
//freopen("in.txt", "r", stdin);
int i;
while (scanf("%ld", &N) && N) {
for (i = 1; i <= N; i++)
scanf("%ld", &Seq[i]);
Cal();
Reset();
}
return 0;
}
我做了调试,但发现很难理解解决方案。
任何人都可以解释这个问题的代码或解决方案。或者,任何人都可以发布代码来解决动态编程而不是递归的问题吗?
答案 0 :(得分:1)
此处的状态为Table[left][right]
,如果您的序列包含left
到right
之间的元素,则表示最佳解决方案。在每个步骤中尝试每个可能的移动 - 从左侧获取N
元素或从右侧获取N
元素,其中N在1
和right - left
之间。
Example:
4 -10 -20 7
从左边开始:
表[1] [4] = max(sum(1,1) - 表[2] [4],sum(1,2) - 表[3] [4], sum(1,3) - 表[4] [4],sum(1,4))。
从右边开始:
表[1] [4] = max(sum(4,4) - 表[1] [3],sum(3,4) - 表[1] [2], sum(2,4) - 表[1] [1],sum(1,4))。
sum(L, R)
是L
和R
之间的数组之和。我因为下一个对手转而减去。