题解 P4363 【[九省联考2018]一双木棋chess】
显然放下的棋子构成一个阶梯型。
我们爆搜一发状态量,发现只有35万多种,这不随便做?
然后在用map记录答案的情况下一发min-max对抗搜索就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define debug cout
typedef long long int lli;
using namespace std;
const int maxn=15,base=12;
const int inf=0x3f3f3f3f;
map<lli,int> mp;
int a[maxn][maxn],b[maxn][maxn];
int hei[maxn]; // hei[0] = n .
int n,m;
inline lli hsh() {
lli ret = 0;
for(int i=1;i<=n;i++) ret = ret * base + hei[i];
return ret;
}
inline void unzip(lli t) {
for(int i=n;i;i--) hei[i] = t % base , t /= base;
}
inline int getnxt() {
int ret = 0;
for(int i=1;i<=n;i++) ret += hei[i];
return ret & 1; // 0 means max , 1 means min .
}
inline int dfs(lli sta) {
if( mp.find(sta) != mp.end() ) return mp[sta];
unzip(sta);
int tpe = getnxt() , ret = tpe ? inf : -inf;
for(int i=1;i<=n;i++)
if( hei[i-1] > hei[i] ) {
++hei[i];
lli h = hsh();
if( !tpe ) ret = max( ret , dfs(h) + a[i][hei[i]] );
else ret = min( ret , dfs(h) - b[i][hei[i]] );
--hei[i];
}
return mp[sta] = ret;
}
int main() {
scanf("%d%d",&n,&m) , hei[0] = 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);
for(int i=1;i<=n;i++) hei[i] = m;
lli full = hsh(); mp[full] = 0;
dfs(0);
printf("%d\n",mp[0]);
return 0;
}