唉,只有AC了这道题才会感叹考场上没有想出解法的我是多么智障。
我甚至连任何想法都没有。
天啊我当时到底在想些什么。
AC这道题我就能进前15了诶。
我们发现只要确定了轮廓线那么此时的状态就是唯一的。
那么,用15进制的状态去表示一下此时的轮廓线。详细说来,就是我们有n个数,第i个数表示第i行放了多少棋子,然后我们把这n个数用15进制表示一下(为什么不是m+1进制呢?qwq因为15进制写着方便),就可以爆搜啦
然后因为开O2的关系,map记忆化一下就可以A啦
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<map>
#define maxs 30000020
#define maxn 120
#define mod 15
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} map<long long,long long>s; long long q[maxn][maxn]; long long f[maxs][];
bool vis[maxs];
long long tot;
long long End;
long long n,m;
long long mul[maxn]; inline void check(long long state){ if(s.count(state)==) s[state]=++tot; } void output(long long ret){
for(long long i=;i<=n;++i){
printf("%lld ",ret%);
ret/=;
}
printf("\n");
return;
} void dfs(long long state){
//output(state);
check(state);
if(vis[s[state]]) return;
vis[s[state]]=;
long long &beta=f[s[state]][],&alpha=f[s[state]][];
if(state==End) return;
beta=0x7fffffff;
long long ret=state,last=m; for(long long i=;i<=n;++i){
long long now=ret%mod;
if(now<last){
long long nxt=state-((state/mul[i-])%mod)*mul[i-];
nxt+=(now+)*mul[i-];
//output(state);
//output(nxt);
//printf("%d\n",now);
dfs(nxt);
beta=min(beta,f[s[nxt]][]);
alpha=max(alpha,f[s[nxt]][]+q[i][now+]);
}
last=now;
ret/=mod;
}
//output(state);
//printf("%lld %lld\n",alpha,beta);
//printf("\n");
return;
} int main(){
n=read(),m=read();
mul[]=;
for(long long i=;i<=n;++i) mul[i]=mul[i-]*mod;
long long ans=;
for(long long i=;i<=n;++i)
for(long long j=;j<=m;++j) q[i][j]=read();
for(long long i=;i<=n;++i)
for(long long j=;j<=m;++j){
long long x=read();
ans-=x;
q[i][j]+=x;
}
for(long long i=;i<=n;++i) End=(End*mod)+m;
dfs();
printf("%lld",f[s[]][]+ans);
return ;
}