p4363 [九省联考2018]一双木棋chess

传送门

分析

我们用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;
}
原文地址:https://www.cnblogs.com/yzxverygood/p/10439157.html