该问题是一个动态规划问题
二人的最佳选择都是选择当前值加上之后选择值的和最大的情况
我们用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];
}