唉,只有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=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } map<long long,long long>s; long long q[maxn][maxn]; long long f[maxs][2]; 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)==0) s[state]=++tot; } void output(long long ret){ for(long long i=1;i<=n;++i){ printf("%lld ",ret%15); ret/=15; } printf(" "); return; } void dfs(long long state){ //output(state); check(state); if(vis[s[state]]) return; vis[s[state]]=1; long long &beta=f[s[state]][0],&alpha=f[s[state]][1]; if(state==End) return; beta=0x7fffffff; long long ret=state,last=m; for(long long i=1;i<=n;++i){ long long now=ret%mod; if(now<last){ long long nxt=state-((state/mul[i-1])%mod)*mul[i-1]; nxt+=(now+1)*mul[i-1]; //output(state); //output(nxt); //printf("%d ",now); dfs(nxt); beta=min(beta,f[s[nxt]][1]); alpha=max(alpha,f[s[nxt]][0]+q[i][now+1]); } last=now; ret/=mod; } //output(state); //printf("%lld %lld ",alpha,beta); //printf(" "); return; } int main(){ n=read(),m=read(); mul[0]=1; for(long long i=1;i<=n;++i) mul[i]=mul[i-1]*mod; long long ans=0; for(long long i=1;i<=n;++i) for(long long j=1;j<=m;++j) q[i][j]=read(); for(long long i=1;i<=n;++i) for(long long j=1;j<=m;++j){ long long x=read(); ans-=x; q[i][j]+=x; } for(long long i=1;i<=n;++i) End=(End*mod)+m; dfs(0); printf("%lld",f[s[0]][1]+ans); return 0; }