题目链接:http://vjudge.net/problem/viewProblem.action?id=19461
思路:一类经典的博弈类区间dp,我们令dp[l][r]表示玩家A从区间[l, r]得到的最大值,于是就有dp[l][r] = sum[l][r] - min(dp[l + i][r], dp[l][r - i]) (i >= 1 && i + l <= r),最终我们要求的就是dp[1][n] - (sum[1][n] - dp[1][n]).
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define RFOR(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;int dp[111][111], sum[111], a[111], N;int dfs(int l, int r)
{if (l > r) return 0;if (~dp[l][r]) return dp[l][r];int res = 0;FOR(i, l + 1, r) {res = min(res, dfs(i, r));}RFOR(i, r - 1, l) {res = min(res, dfs(l, i));}return dp[l][r] = sum[r] - sum[l - 1] - res;
}int main()
{while (cin >> N && N) {FOR(i, 1, N) cin >> a[i], sum[i] = sum[i - 1] + a[i];memset(dp, -1, sizeof(dp));cout << 2 * dfs(1, N) - sum[N] << endl;}return 0;
}
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4597
这道题和上一题差不多,只是多了维数,dp[al][ar][bl][br]表示从第一堆的al~ar和第二堆的bl~br中取得的最大值.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;int a[22], b[22], N;
int dp[22][22][22][22];int dfs(int al, int ar, int bl, int br, int sum)
{if (al > ar && bl > br) return 0;if (~dp[al][ar][bl][br]) return dp[al][ar][bl][br];int res = 0;if (al <= ar) {res = max(res, sum - dfs(al + 1, ar, bl, br, sum - a[al]));res = max(res, sum - dfs(al, ar - 1, bl, br, sum - a[ar]));}if (bl <= br) {res = max(res, sum - dfs(al, ar, bl + 1, br, sum - b[bl]));res = max(res, sum - dfs(al, ar, bl, br - 1, sum - b[br]));}return dp[al][ar][bl][br] = res;
}int main()
{int Cas; cin >> Cas;while (Cas--) {cin >> N; int sum = 0;FOR(i, 1, N) cin >> a[i], sum += a[i];FOR(i, 1, N) cin >> b[i], sum += b[i];memset(dp, -1, sizeof(dp));cout << dfs(1, N, 1, N, sum) << endl;}return 0;
}