谁能解释一下这个记忆/动态编程问题/谜题的解决方案?
这是问题陈述:
这是一个两人游戏。最初,数组中有 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;
}
我确实调试了它,但发现很难理解解决方案。
谁能解释一下这个问题的代码或解决方案。或者任何人都可以发布代码来用动态编程而不是递归来解决这个问题?
This is the problem statement:
This is a two player game. Initially there are n integer numbers in an array and players A and B get chance to take them alternatively. Each player can take one or more numbers from the left or right end of the array but cannot take from both ends at a time. He can take as many consecutive numbers as he wants during his time. The game ends when all numbers are taken from the array by the players. The point of each player is calculated by the summation of the numbers, which he has taken. Each player tries to achieve more points from other. If both players play optimally and player A starts the game then how much more point can player A get than player B?
Input
The input consists of a number of cases. Each case starts with a line specifying the integer
n (0 < n ≤100)
, the number of elements in the array. After that,n
numbers are given for the game. Input is terminated by a line wheren=0
.Output
For each test case, print a number, which represents the maximum difference that the first player obtained after playing this game optimally.
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
This is the solution of this problem.
#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;
}
I did debug it but found it difficult to understand the solution.
Can anyone explain the code or the solution of this problem. Or can anyone post code to solve this problem with dynamic programming not recursion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的状态是
Table[left][right]
,如果您有一个包含从left
到right
的元素的序列,它代表最佳解决方案包容性。在每一步中都会尝试每种可能的移动 - 从左侧获取N
个元素或从右侧获取N
个元素,其中 N 介于1
和 <代码>右 - 左。从左边看:
从右边开始:
sum(L, R)
是L
和R
之间的数组编号之和。我因为下一个对手回合而减去。The state here is
Table[left][right]
which represents the best solution if you have a sequence that includes the elements fromleft
toright
inclusive. At each step every possible move is tried - takeN
elements from the left orN
elements from the right, where N is between1
andright - left
.Take from the left:
Take from the right:
sum(L, R)
is the sum of array numbers betweenL
andR
. I am subtracting because of the next opponent turn.