[bzoj2331][SCOI2011]地板【插头dp】
【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=2331
【题解】
可以用插头dp的方式表示状态。
每一位用一个三进制位表示,0表示没有木块向该方向连通,1表示有木块,且还未拐弯。2表示有木块并且拐弯了。
时间复杂度
/* --------------
user Vanisher
problem bzoj-2331
----------------*/
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define P 20110520
# define N 110
# define T 11
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
vector <int> g[2],f[2];
int n,m,f1,f2,nex[N],now[N],h[1<<(2*T)],lim;
char mp[N][N],ne[N][N];
int getnum(){
int cnt=0;
for (int i=0; i<=m; i++) cnt=cnt+(nex[i]<<(i*2));
return cnt;
}
void join(int num){
int tmp=getnum();
if (h[tmp]==-1){
h[tmp]=g[f2].size();
g[f2].push_back(tmp);
f[f2].push_back(num);
}
else f[f2][h[tmp]]=(f[f2][h[tmp]]+num)%P;
}
int main(){
n=read(), m=read();
for (int i=0; i<n; i++)
scanf("\n%s",mp[i]);
if (n<m){
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
ne[j][i]=mp[i][j];
swap(n,m);
for (int i=0; i<n; i++)
for (int j=0; j<m; j++)
mp[i][j]=ne[i][j];
}
f1=0, f2=1, lim=1<<(2*m+2);
g[f1].push_back(0); f[f1].push_back(1);
memset(h,-1,sizeof(h));
for (int i=0; i<n; i++){
for (int j=0; j<m; j++){
for (unsigned k=0; k<g[f1].size(); k++){
int tmp=g[f1][k], num=f[f1][k];
if (tmp>=lim) continue;
for (int t=0; t<=m; t++) now[t]=nex[t]=(tmp>>(t*2))&3;
if (mp[i][j]=='*'){
if (now[j]==0&&now[j+1]==0) join(num);
}
else {
if (now[j]==0&&now[j+1]==0){
nex[j]=2, nex[j+1]=2; join(num);
nex[j]=1, nex[j+1]=0; join(num);
nex[j]=0, nex[j+1]=1; join(num);
}
if (now[j]!=0&&now[j+1]==0){
if (now[j]==1){
nex[j]=2, nex[j+1]=0; join(num);
nex[j]=0, nex[j+1]=1; join(num);
}
else {
nex[j]=0, nex[j+1]=2; join(num);
nex[j]=0, nex[j+1]=0; join(num);
}
}
if (now[j]==0&&now[j+1]!=0){
if (now[j+1]==1){
nex[j]=1, nex[j+1]=0; join(num);
nex[j]=0, nex[j+1]=2; join(num);
}
else {
nex[j]=2, nex[j+1]=0; join(num);
nex[j]=0, nex[j+1]=0; join(num);
}
}
if (now[j]==1&&now[j+1]==1){
nex[j]=0, nex[j+1]=0; join(num);
}
}
}
g[f1].clear(), f[f1].clear();
for (unsigned k=0; k<g[f2].size(); k++) h[g[f2][k]]=-1;
swap(f1,f2);
}
for (unsigned k=0; k<g[f1].size(); k++) g[f1][k]<<=2;
}
for (unsigned i=0; i<g[f1].size(); i++)
if (g[f1][i]==0){
printf("%d\n",f[f1][i]);
return 0;
}
printf("0\n");
return 0;
}