Luogu P4363 [九省联考2018]一双木棋chess
组合游戏
当一个游戏满足如下几个性质:
1.每个人都足够聪明
2.游戏可以化归到有向无环图上
3.游戏的内容是确定的
则称这个游戏是组合游戏
Solution
该题中的游戏很明显是个组合游戏,另外题目中有条件“菲菲和牛牛都希望,自己的得分减去对方的得分得到的结果最大”,如果菲菲的贡献为正,牛牛的贡献为负,也就是说一个人希望总贡献最大,另一个人希望总贡献最小,对抗搜索就好了。
Code:
//直接用map存了状态,吸氧才过了
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 20;
int n,m;
struct State{
int num[MAXN];
bool operator < (const State &x)const{
for (int i = 1; i <= n; i++) {
if (num[i] != x.num[i]) return num[i] < x.num[i];
}
return false;
}
};
map<State,int> dp1,dp2;
int a[MAXN][MAXN],b[MAXN][MAXN];
int DFS2(State s);
int DFS1(State s) {
if (dp1.find(s) != dp1.end()) return dp1[s];
int ret = -1e9;
for (int i = 1; i <= n; i++) {
if (i == n && s.num[n] == m - 1 && s.num[n - 1] == m) return a[n][m];
if (s.num[i] < m && (i == 1 || s.num[i] < s.num[i - 1])) {
s.num[i]++;
ret = max(ret,a[i][s.num[i]] + DFS2(s));
s.num[i]--;
}
}
return dp1[s] = ret;
}
int DFS2(State s) {
if (dp2.find(s) != dp2.end()) return dp2[s];
int ret = 1e9;
for (int i = 1; i <= n; i++) {
if (i == n && s.num[n] == m - 1 && s.num[n - 1] == m) return -b[n][m];
if (s.num[i] < m && (i == 1 || s.num[i] < s.num[i - 1])) {
s.num[i]++;
ret = min(ret,-b[i][s.num[i]] + DFS1(s));
s.num[i]--;
}
}
return dp2[s] = ret;
}
int main() {
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d",&a[i][j]);
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d",&b[i][j]);
}
}
State begin;
memset(begin.num,0,sizeof(begin.num));
printf("%d\n",DFS1(begin));
return 0;
}