LOJ #2471. 「九省联考 2018」一双木棋 记忆化搜索
简单记忆化搜索.
显然,数字的形态是类似阶梯下降的,状态数不会太多,记忆化爆搜就行.
code:
#include <bits/stdc++.h> #define N 12 #define mod 1000000007 #define base 12 #define ll long long #define inf 1000000000 #define setIO(s) freopen(s".in","r",stdin) using namespace std; map<ll,int>vis; map<ll,int>fin; int n,m; int cur[12],A[12][12],B[12][12]; ll ha() { ll an=1; for(int i=1;i<=n;++i) { if(!cur[i]) break; an=an*base+cur[i]; } return an; } // 非 - 黑 - A // 牛 - 白 - B // d=1:非走;d=0 : 牛走 // d=1: f[now]=max(f[now],a[选]+f[now+a]); // d=0: f[now]=min(f[now],-b[选]+f[now+a]); int solve(int d) { ll cu=ha(); if(vis[cu]) return fin[cu]; vis[cu]=1; int tmp=(d==1?-inf:inf); for(int i=1;i<=n;++i) { if(cur[i]<cur[i-1]) { ++cur[i]; if(d==1) tmp=max(tmp,A[i][cur[i]]+solve(d^1)); else tmp=min(tmp,-B[i][cur[i]]+solve(d^1)); --cur[i]; } } fin[cu]=tmp; return tmp; } int main() { // setIO("input"); int i,j; 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]); cur[0]=m; for(i=1;i<=n;++i) cur[i]=m; ll c=ha(); vis[c]=1; fin[c]=0; for(i=1;i<=n;++i) cur[i]=0; printf("%d\n",solve(1)); return 0; }