该问题是一个动态规划问题
二人的最佳选择都是选择当前值加上之后选择值的和最大的情况
我们用maxValue[i][j]表示在剩余硬币为i~j的时候,二人可以拿到的最大和值;用select[i][j]表示在在剩余硬币为i~j的时候,选择的硬币标号。
当只剩1个硬币的时候: maxValue[i][i] = v[i]
当只剩2个硬币的时候: maxValue[i][j] = max(v[i], v[i + 1])
当剩余硬币大于等于3个时,需要知道自己拿完后另一个人的策略:
1.当自己拿的是编号最小的硬币:
1.另一个人拿的是编号最大的硬币,自己之后可以拿到的最大和值为:first = v[i] + maxValue[i + 1][j - 1];
2.另一个人拿的也是编号最小的硬币,自己之后可以拿到的最大和值为:first = v[i] + maxValue[i + 2][j];
2.当自己拿的是编号最大的硬币:
1.另一个人拿的是编号最小的硬币,自己之后可以拿到的最大和值为:last = maxValue[i + 1][j - 1] + v[j];
2.另一个人拿的也是编号最大的硬币,自己之后可以拿到的最大和值为:last = maxValue[i][j - 2] + v[j];
所以,这时自己应该拿到的最大和值尾max(first, last)。
#include<stdio.h>
#include<memory.h>
#define N 100
int
v[N];
int
maxValue[N][N];
int
select[N][N];
int
MaxValue(
int
v[],
int
n);
int
main(){
int
n;
while
(EOF !=
scanf
(
"%d"
, &n)){
for
(
int
i = 0; i < n; i++){
scanf
(
"%d"
, &v[i]);
}
printf
(
"%d"
, MaxValue(v, n));
}
}
int
MaxValue(
int
v[],
int
n){
int
i, j, len;
for
(i = 0; i < n; i++)
maxValue[i][i] = v[i];
select[i][i] = i;
for
(i = 0; i < n - 1; i++){
if
(v[i] > v[i + 1]){
maxValue[i][i + 1] = v[i];
select[i][i + 1] = i;
}
else
{
maxValue[i][i + 1] = v[i + 1];
select[i][i + 1] = i + 1;
}
}
for
(len = 3; len <= n; len++){
for
(i = 0; i < n - len + 1; i++){
j = i + len - 1;
int
first, last;
if
(select[i + 1][j] == j)
first = v[i] + maxValue[i + 1][j - 1];
else
if
(select[i + 1][j] == i + 1)
first = v[i] + maxValue[i + 2][j];
if
(select[i][j - 1] == i)
last = maxValue[i + 1][j - 1] + v[j];
else
if
(select[i][j - 1] == j - 1)
last = maxValue[i][j - 2] + v[j];
if
(first > last){
maxValue[i][j] = first;
select[i][j] = i;
}
else
{
maxValue[i][j] = last;
select[i][j] = j;
}
}
}
return
maxValue[0][n - 1];
}