染色大战是在一个 n × m 的棋盘上进行的游戏,棋盘的每个节点要么是白色,要么是黑色。
节点的编号方式为:
Sample Input
3 3
0 0 0
0 0 0
0 0 0
3 2
5 1
Sample Output
-1
数据范围
30% 的数据, n = m = 3
100% 的数据, 3 ≤ n, m ≤ 6, n × m ≤ 20, 0 ≤ ai,j ≤ 1, 1 ≤ wi,j ≤ 100
典型的博弈问题
设f[u][id]为当前局面为u(0为A;1为B)操作,染色情况为id(的二进制【0为黑一位白】)时的A的最大得分减去B的最大得分。
然后用dfs求解。
转移方程为:
f[0][id]=max(f[u’][id+k]+score)
f[1][id]=min(f[u’][id+k]-score)
score为当前这一步可得的分,为0时不必加(废话。。。)
注意:
1、记忆化:如果需要的f[u’][id+k]已被更新过,就不必dfs,可直接调用;。
2、如果得分则继续自己染色,u’=u染色
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=2000000001;
const int maxn=1<<20;
const int N=6+2;
int f[2][maxn],vis[maxn];
int n,m,a[N][N],v[N][N];
inline int bedo(int id,int i,int j){
int x=i*m+j+1;
return id|(1<<(n*m-x));
}
int score(int id,int i,int j){
bool lu,u,ru,l,r,ld,d,rd;
lu=u=ru=l=r=ld=d=rd=false;
if(i>0&&j>0&&id==bedo(id,i-1,j-1)) lu=true;
if(i>0&&id==bedo(id,i-1,j)) u=true;
if(i>0&&j<m-1&&id==bedo(id,i-1,j+1)) ru=true;
if(j>0&&id==bedo(id,i,j-1)) l=true;
if(j<m-1&&id==bedo(id,i,j+1)) r=true;
if(i<n-1&&j>0&&id==bedo(id,i+1,j-1)) ld=true;
if(i<n-1&&id==bedo(id,i+1,j)) d=true;
if(i<n-1&&j<m-1&&id==bedo(id,i+1,j+1)) rd=true;
int ret=0;
if(lu&&u&&l) ret+=v[i-1][j-1];
if(ru&&u&&r) ret+=v[i-1][j];
if(ld&&d&&l) ret+=v[i][j-1];
if(rd&&d&&r) ret+=v[i][j];
return ret;
}
int dfs(int x,int id)
{
if(id==(1<<(n*m))-1) return 0;
int k;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(id!=(k=bedo(id,i,j)))
{
int now=score(id,i,j);
if(!now)
if(!x)
if(f[1][k]==inf)
f[0][id]=max(f[0][id],dfs(1,k));
else
f[0][id]=max(f[0][id],f[1][k]);
else
if(f[0][k]==-inf)
f[1][id]=min(f[1][id],dfs(0,k));
else
f[1][id]=min(f[1][id],f[0][k]);
else
if(!x)
if(f[0][k]==-inf)
f[0][id]=max(f[0][id],dfs(0,k)+now);
else
f[0][id]=max(f[0][id],f[0][k]+now);
else
if(f[1][k]==inf)
f[1][id]=min(f[1][id],dfs(1,k)-now);
else
f[1][id]=min(f[1][id],f[1][k]-now);
}
return f[x][id];
}
int main()
{
for(int i=0;i<maxn;i++) f[0][i]=-inf;
for(int i=0;i<maxn;i++) f[1][i]=inf;
cin>>n>>m;
int id=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
scanf("%d",&a[i][j]);
id=id*2+a[i][j];
}
for(int i=0;i<n-1;i++)
for(int j=0;j<m-1;j++)
scanf("%d",&v[i][j]);
// /*it is debug->*/ for(int i=0;i<(1<<(n*m));i++) printf("%d %d\n",f[0][i],f[1][id]);
printf("%d",dfs(0,id));
return 0;
}