容易写出暴力.
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 11,inf = 1e9+7,M = 1e6+50;
int n,m,a[N][N],b[N][N];
bool vis[N][N];
int dfs(int x,int y,bool k)
{
if(x == n && y == m) return k ? -b[x][y] : a[x][y];
int ans = k ? -inf : inf;
vis[x][y] = 1;
rep(i,1,n) rep(j,1,m)
if(vis[i - 1][j] && vis[i][j - 1] && !vis[i][j]){
if(k)
{
ans = max(ans,dfs(i,j,k^1) - b[x][y]);
}
else ans = min(ans,dfs(i,j,k^1) + a[x][y]);
}
vis[x][y] = 0;
return ans;
}
int main()
{
read(n); read(m);
rep(i,1,n) rep(j,1,m)
read(a[i][j]);
rep(i,1,n) rep(j,1,m)
read(b[i][j]);
rep(i,0,m) vis[0][i] = 1;
rep(i,0,n) vis[i][0] = 1;
cout << dfs(1,1,0) << endl;
return 0;
}
上述代码50分.
考虑如何优化
发现其实每一层当前能选的都是固定的.
那么考虑状压来表示出每一层的状态.
因为m最大为10,根据题意显然总变化不会超过10
用1表示向左边移动,0表示该层结束
那么可以用f[i][j]表示第一层从i开始,接下来状态为j
比如i = 5,j = 111010(2进制)
表示第一层为5 ,第二层为5,第三层为4,第五层为1,接下来的层均为1.
那么这样表示发现状态一定不会超过2^20
然后考虑转移即可。
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x; i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
x = 0;char c;int sign = 1;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 21,inf = 0x3f3f3f3f,M = 1e6+50;
int n,m,a[N][N],b[N][N],f[N][1<<N];
int solve(int x)
{
int p[50],len = 0;
while(x)
{
p[++len] = x&1;
x >>= 1;
}
repd(i,len,1) printf("%d",p[i]);
puts("");
}
int dfs(int x,int s,bool k)
{
if(f[x][s] != inf) return f[x][s];
if(x == m && !s) return f[x][s] = 0;
f[x][s] = k ? inf : -inf;
int p[N],y = 0,S = s,len = 1;
memset(p,0,sizeof p); p[1] = x;
while(S)
{
if(!(S&1)) p[++len] = x - y;
else ++y;
S >>= 1;
}
while(++len <= n) p[len] = x - y;
if(x != m)
if(!k) f[x][s] = max(dfs(x + 1,s<<1|1,k^1) + a[1][x + 1],f[x][s]);
else f[x][s] = min(dfs(x + 1,s<<1|1,k^1) - b[1][x + 1],f[x][s]);
rep(i,2,n)
if(p[i] != p[i-1]){
y = 0;
++p[i];
repd(j,n,2)
{
int k = p[j - 1] - p[j];
while(k--) y = y<<1|1;
y <<= 1;
}y>>=1;
if(!k) f[x][s] = max(dfs(x,y,k^1) + a[i][p[i]],f[x][s]);
else f[x][s] = min(dfs(x,y,k^1) - b[i][p[i]],f[x][s]);
--p[i];
}
return f[x][s];
}
int main()
{
memset(f,0x3f,sizeof f);
read(n); read(m);
rep(i,1,n) rep(j,1,m)
read(a[i][j]);
rep(i,1,n) rep(j,1,m)
read(b[i][j]);
cout << dfs(1,1,1) + a[1][1] << endl;
return 0;
}