题面:
分析:
- 暴力:
暴搜出每种状态下每个人的最优决策,期望得分:(30pts)
- 正解
我们通过模拟可以发现,最终选择出来的状态一定是呈现出梯形的样子,所以我们联想到针对形状的 轮廓线DP,我们规定横边用 (0) 表示,竖边用 (1) 表示,每一个状态从右上到左下可表示为一组长度为 (n+m-2) 的 (01) 序列
序列的初始值是 (0dots(m-1个) 1dots(n-1个)),结束值是 (1dots(n-1个) 0dots(m-1个))
每一次状态转移相当于把一对 (01 o10)
复杂度是 (O(2^{n+m-2}log))
- 另解
对于一人求局面最小值,一人求局面最大值,典型的 (min-max) 搜索,但是单纯的 (min-max) 搜索复杂度不对,需要进行 (alpha-eta) 剪枝 (日后再填坑吧)
代码:
#include<bits/stdc++.h>
using namespace std;
namespace zzc
{
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const int maxn = 10;
const int maxm = (1<<(maxn<<1));
const int inf = 1e9+7;
bool vis[maxm];
int f[maxm],a[maxn][maxn],b[maxn][maxn];
int n,m;
int dfs(int st,int who)
{
if(vis[st]) return f[st];
f[st]=who?-inf:inf;
int x=n,y=0;
for(int i=0;i<n+m-1;i++)
{
if((st>>i)&1) x--;
else y++;
if((st>>i&3)!=1) continue;
int to=st^(3<<i);
if(who) f[st]=max(f[st],dfs(to,who^1)+a[x][y]);
else f[st]=min(f[st],dfs(to,who^1)-b[x][y]);
}
vis[st]=true;
return f[st];
}
void work()
{
n=read();m=read();
for(int i=0;i<n;i++) for(int j=0;j<m;j++) a[i][j]=read();
for(int i=0;i<n;i++) for(int j=0;j<m;j++) b[i][j]=read();
f[((1<<n)-1)<<m]=0;
vis[((1<<n)-1)<<m]=true;
printf("%d
",dfs((1<<n)-1,1));
}
}
int main()
{
zzc::work();
return 0;
}