P8172
魔怔题。太不牛了。
下文
首先考虑
转移分四种情况讨论。
以上转移还需要判断是否合法,也是容易的,不多讲。
这样就能得到一个
考虑
然后充分发挥想象力,首先手玩一下,发现除了转移一之外的所有转移,在经过
然后观察(或打表)发现对于一个状态,它能转移到的状态根据行数是指数级增长的。于是大胆猜测:如果两个关键行间距离较远,则删去
具体地,考虑两个相邻的关键行是
时间复杂度
code:
int n,m,k,X[M],Y[M],a[17][M],f[17][N],dp[N];
vector<int> g;
map<int,int> id;
void Yorushika(){
read(n,m,k);
int s=0;
rep(i,1,k){
read(X[i],Y[i]);
g.eb(Y[i]);
}
g.eb(m),g.eb();
sort(g.begin(),g.end());
g.erase(unique(g.begin(),g.end()),g.end());
int lst=0;
for(int i:g){
id[i]=id[lst]+min(i-lst,((i-lst-1)%6+13));
lst=i,m=id[i];
}
rep(i,1,k){
a[X[i]][id[Y[i]]]=1;
if(Y[i]==1){
s|=1<<(X[i]-1);
}
}
dp[s]=1;
const int mx=1<<n;
cerr<<m<<'\n';
rep(i,1,m-1){
mems(f,0);
rep(S,0,mx-1){
f[0][S]=dp[S];
}
rep(j,0,n-1){
rep(S,0,mx-1){
if(!f[j][S]){
continue;
}
int x=S>>j&1,y=S>>(j+1)&1;
if(j<n-1&&x&&!y&&!a[j+1][i+1]&&!a[j+2][i+1]){
int T=S|(1<<j)|(1<<(j+1));
f[j+2][T]|=f[j][S];
}
if(j<n-1&&!x&&y&&!a[j+1][i+1]&&!a[j+2][i+1]){
int T=S|(1<<j)|(1<<(j+1));
f[j+2][T]|=f[j][S];
}
if(j<n-1&&!x&&!y&&!a[j+1][i+1]){
int T=S|(1<<j)|((a[j+2][i+1])<<(j+1));
f[j+2][T]|=f[j][S];
}
if(j<n-1&&!x&&!y&&!a[j+2][i+1]){
int T=S|(1<<(j+1))|((a[j+1][i+1])<<j);
f[j+2][T]|=f[j][S];
}
if(j<n-2&&!x&&!y&&!(S>>(j+2)&1)&&!a[j+1][i+1]&&!a[j+2][i+1]&&!a[j+3][i+1]){
int T=S|(1<<j)|(1<<(j+1))|(1<<(j+2));
f[j+3][T]|=f[j][S];
}
if(x){
int T=(S^(1<<j))|(a[j+1][i+1]<<j);
f[j+1][T]|=f[j][S];
}
}
}
rep(S,0,mx-1){
dp[S]=f[n][S];
}
}
puts(dp[mx-1]?"YES":"NO");
}
signed main(){
int t=1;
//read(t);
while(t--){
Yorushika();
}
}
upd:被 hack 了,原因是 id[i]=id[lst]+min(i-lst,((i-lst-1)%6+7)); 中间留的行数不够。看官方题解似乎是要留