计蒜客 取数游戏 博弈+dp
2017-04-27 08:15
162 查看
题目链接
取数游戏
思路:dp(x, y)表示先手在区间[x, y]能取得的最大分数。当先手取完,就轮到后手去,后手一定会选择当前能令他得到最大分数的策略,其实当先手在[x, y]区间两端取走一个数,那么后手面临两个状态[x+1, y]和[x, y-1],先手想要取得最大值,一定会想让后手取这两种状态中的较小值,设[x, y]区间的数字和为sum,转移方程就是dp(x, y) = max{sum - dp(x+1, y), dp(x, y-1)}。边界就是只有一个数的时候,即x==y.
关于博弈思想:当先手取后,后手取的时候,后手其实也是看做一个先手处理,只是面临的状态不同而已,这样就非常容易理解了。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 100+5;
int a[maxn], dp[maxn][maxn], sum[maxn];
int dfs(int x, int y) {
if(dp[x][y] != -1) return dp[x][y];
if(x == y) return dp[x][y] = a[x];
int left = dfs(x+1, y);
int right = dfs(x, y-1);
int tol = sum[y] - sum[x-1]; //[x, y]的和
dp[x][y] = max(tol - left, tol - right);
return dp[x][y];
}
int main() {
int n;
while(scanf("%d", &n) == 1) {
sum[0] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
memset(dp, -1, sizeof(dp));
int ans = dfs(1, n);
printf("%d %d\n", ans, sum
- ans);
}
return 0;
}
如有不当之处欢迎指出!
取数游戏
思路:dp(x, y)表示先手在区间[x, y]能取得的最大分数。当先手取完,就轮到后手去,后手一定会选择当前能令他得到最大分数的策略,其实当先手在[x, y]区间两端取走一个数,那么后手面临两个状态[x+1, y]和[x, y-1],先手想要取得最大值,一定会想让后手取这两种状态中的较小值,设[x, y]区间的数字和为sum,转移方程就是dp(x, y) = max{sum - dp(x+1, y), dp(x, y-1)}。边界就是只有一个数的时候,即x==y.
关于博弈思想:当先手取后,后手取的时候,后手其实也是看做一个先手处理,只是面临的状态不同而已,这样就非常容易理解了。
AC代码
#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstring>
#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define eps 1e-10
#define inf 0x3f3f3f3f
#define PI pair<int, int>
typedef long long LL;
const int maxn = 100+5;
int a[maxn], dp[maxn][maxn], sum[maxn];
int dfs(int x, int y) {
if(dp[x][y] != -1) return dp[x][y];
if(x == y) return dp[x][y] = a[x];
int left = dfs(x+1, y);
int right = dfs(x, y-1);
int tol = sum[y] - sum[x-1]; //[x, y]的和
dp[x][y] = max(tol - left, tol - right);
return dp[x][y];
}
int main() {
int n;
while(scanf("%d", &n) == 1) {
sum[0] = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
memset(dp, -1, sizeof(dp));
int ans = dfs(1, n);
printf("%d %d\n", ans, sum
- ans);
}
return 0;
}
如有不当之处欢迎指出!
相关文章推荐
- 计蒜客/阿里的新游戏
- noi 9265 取数游戏
- 洛谷 P1288 取数游戏II
- P1288 取数游戏II
- 计蒜客 跳跃游戏
- 【区间DP+高精】codevs1166 矩阵取数游戏题解
- 【u108】取数游戏
- 计蒜客第18题---跳跃游戏
- 计蒜客-跳跃游戏
- 计蒜客 —— 乘法游戏
- bzoj 1413: [ZJOI2009]取石子游戏(博弈+DP)
- 1978: [BeiJing2010]取数游戏 game
- wikioi 1037 取数游戏
- 9265:取数游戏 题解
- 【CodeVS1037】取数游戏
- 洛谷P1288 取数游戏II
- 计蒜客【跳跃游戏二】
- 计蒜客--第18题:跳跃游戏
- BZOJ1978: [BeiJing2010]取数游戏 game
- 计蒜客 跳跃游戏 贪心