题目:
给出一串数组,两人博弈,统计两人拿到的总数,求先手赢对手的最大值.
这道题小白上也有,做的时候觉得有做过类似的跑回去找找看,后来发现是一样的.不过第一次做的时候没理解透,觉得样例输出不是最优解,今天才真的明白.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <algorithm>
using namespace std;
const int MAXN = 110;
int dp[MAXN][MAXN];
int a[MAXN], sum[MAXN];
int n;
int main() {
while(scanf("%d", &n) != EOF && n) {
for(int i=1; i<=n; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
memset(dp, 0, sizeof(dp));
for(int i=1; i<=n; i++) dp[i][i] = a[i];
for(int i=2; i<=n; i++)
for(int j=1, k=i; k<=n; k++, j++) {
int ans = sum[k] - sum[j-1];
for(int r=j; r<k; r++) {
int m = min(dp[j][r], dp[r+1][k]);//后手最优最小值
m = sum[k] - sum[j-1] - m;//先手最优值(基于总数一定)
if(ans < m) ans = m;
}
dp[j][k] = ans;
}
printf("%d\n", 2*dp[1][n]-(sum[n]));//同样基于总数一定(先手取了最优,则余下为后手所得)
}
return 0;
}
思路:
主要的思路就是求出后手最劣的最优,既 m = min(dp[j][r], dp[r+1][k])所有区间基于次级区间,最终都将取完,既m = sum[k]-sum[j-1]-m;