【发布时间】:2011-11-16 10:38:24
【问题描述】:
这是问题陈述:
这是一个两人游戏。最初,数组中有 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;
}
我确实调试了它,但发现解决方案很难理解。
谁能解释一下这个问题的代码或解决方案。或者任何人都可以发布代码以使用动态编程而不是递归来解决这个问题?
【问题讨论】:
-
是的,规则和代码都齐全了。
-
@Cephron - 有负数。有时取所有数字并不好。
-
@Petar - “他可以在他的时间里取任意多的连续数字。” - 我将其解释为,它可以从一端开始,只需通过连续的数字就可以到达另一端。 Edit 啊,好的。错过了负数。谢谢。
标签: c algorithm dynamic-programming memoization