该问题是一个动态规划问题
二人的最佳选择都是选择当前值加上之后选择值的和最大的情况
我们用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 100intv[N];intmaxValue[N][N];intselect[N][N];intMaxValue(intv[],intn);intmain(){ intn; while(EOF
!= scanf("%d",
&n)){ for(inti
= 0; i < n; i++){ scanf("%d",
&v[i]); } printf("%d",
MaxValue(v, n)); }}intMaxValue(intv[], intn){ inti,
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; intfirst,
last; if(select[i
+ 1][j] == j) first
= v[i] + maxValue[i + 1][j - 1]; elseif(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]; elseif(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; } } } returnmaxValue[0][n
- 1];}
动态规划解决硬币游戏
1362

被折叠的 条评论
为什么被折叠?



