题目:
题解:
考试的时候就打了25pts的暴力分
其实从暴力的做法是可以得到启迪的。
我们把所有搜索的状态记录下来,然后如果这一步该A走,就在可以走的几步中选择Max的状态走;如果这一步该B走,就在可以走的几步中选择Min的状态走,这应该是所谓的对抗搜索
考虑一下所有的状态,一定是一个从上往下的阶梯型
因为n,m<=10
所以我们可以用一个n位的m+1进制数把当前下完的轮廓给哈希一下,即第几排选到了第几个。
那么,对于一个局面,我们可以记忆化搜索,
我们只需要根据局面当前下子的是谁,决定这个状态是最大还是最小。这样用map压下当前所有状态,直接搜索即可。。
不要忘记初始化,即最后全选完的时候mmp=0
代码:
#include <map>
#include <cstdio>
#define LL long long
#define INF 1e9
using namespace std;
const LL base=11;
const int N=15;
int h[N],n,m,a[N][N],b[N][N];map<LL,int>mmp;
void unhash(LL st){for (int i=n;i>=1;i--) h[i]=st%base,st/=base;}
int up(){int sb=0;for (int i=1;i<=n;i++) sb+=h[i];return sb&1;}//1 Bob 0 Alice
LL nxt(){LL sb=0;for (int i=1;i<=n;i++) sb=sb*base+(LL)h[i];return sb;}
int dfs(LL st)
{
if (mmp.count(st)) return mmp[st];
unhash(st);
int id=up(),ans;
if (!id) ans=-INF;else ans=INF;
for (int i=1;i<=n;i++)
if (h[i-1]>h[i])
{
h[i]++;
LL now=nxt();
if (!id) ans=max(ans,dfs(now)+a[i][h[i]]);else ans=min(ans,dfs(now)-b[i][h[i]]);
h[i]--;
}
return mmp[st]=ans;
}
int main()
{
// freopen("chess.in","r",stdin);
// freopen("chess.out","w",stdout);
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]);
h[0]=m;//第0行相当于是全填满了
LL all=0;
for (int i=1;i<=n;i++) all=all*base+m;
mmp[all]=0;
printf("%d",dfs(0));
}