传送门

分析

我们用0表示向右,1表示向上

于是可以得到一条江棋盘分为两块的线

直接dp即可

代码



#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int inf = 1e9+7;
int n,m,dp[3001000],a[110][110],b[110][110],M;
bool vis[3001000];
inline int work(int msk,int wh){
if(vis[msk])return dp[msk];
int res=wh?-inf:inf;
vis[msk]=1;
for(int i=0,j=n+1,k=1;i<n+m;i++){
if(!(msk&(1<<i)))k++;
else j--;
if(i==n+m-1||((msk>>i)&3)!=1)continue;
if(wh)res=max(res,work(msk^(3<<i),wh^1)+a[j][k]);
else res=min(res,work(msk^(3<<i),wh^1)-b[j][k]);
}
return dp[msk]=res;
}
int main(){
int i,j,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&a[i][j]);
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&b[i][j]);
M=(1<<(n+m))-1;
vis[((1<<n)-1)<<m]=1;
printf("%d",work((1<<n)-1,1));
return 0;
}