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

SOL:

   我们发现轮廓线一定是单调不减的。 所以这个博弈的总状态数只有10C20 种呢。

    算一下 有184756 种状态,大力dp一下就好了啦。

#include<bits/stdc++.h>
#define LL long long
#define inf (1ll<<51)
#define sight(x) ('0'<=x&&x<='9')
using namespace std;
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('
'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
map<LL,int> dp;
LL pd;
int a[17][17],n,m,b[17],x,sum;
inline LL Hash(){
    static LL anw,i;
    for (anw=0,i=1;i<=n;i++) anw=anw*11+b[i]; return anw;
}
inline void push(LL anw) {
    for (int i=n;i;i--) b[i]=anw%11,anw/=11;
}
LL dfs(LL x){
    if (dp.count(x)) return dp[x];
    push(x); LL ha,t,res;
    t=1;
    for (int i=1;i<=n;i++) t^=b[i]&1;
    if (t) res=inf; else res=-inf;// 先手试图min 
    for (int i=1;i<=n;i++) 
    if (b[i-1]>b[i]){
        b[i]++;
        ha=Hash();
        if (t) res=min(dfs(ha),res);
        else res=max(dfs(ha)+a[i][b[i]],res);
        b[i]--;
    }
    return dp[x]=res;
}
signed main () {
//    freopen("chess.in","r",stdin); 
    read(n); read(m);
    for(int i=1;i<=n;i++)
     for(int j=1;j<=m;j++)
      read(a[i][j]),sum+=a[i][j];
     for(int i=1;i<=n;i++) 
      for(int j=1;j<=m;j++)
       read(x),a[i][j]+=x; b[0]=m;
     for (int i=1;i<=n;i++) pd=pd*11+m;
     dp[pd]=0;
     writeln(sum-dfs(0)); 
     return 0;
} 
原文地址:https://www.cnblogs.com/rrsb/p/8782939.html