lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。
R*C<=100
插头dp。
用0表示没有插头,1表示有插头且可以转弯,2表示有插头但不能转弯。
接下来就是枚举各种转移了。
1.00-->22 或 10 或 01
2.11-->00
3.10-->20 或 01
20-->00 或 02
4.01-->10 或 02
02-->00 或 20
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> #define M 200005 #define mod 20110520 using namespace std; char s[105]; int bit[105],h[50005],tot,now,pre,a[105][105],n,m,f[2][M],state[2][M],total[2]; struct edge { int y,ne; }e[M]; void Solve(int s,int num) { int pos=s%50000; for (int i=h[pos];i;i=e[i].ne) if (state[now][e[i].y]==s) { (f[now][e[i].y]+=num)%=mod; return; } total[now]++; state[now][total[now]]=s; f[now][total[now]]=num; e[++tot].y=total[now],e[tot].ne=h[pos],h[pos]=tot; } void Plugdp() { now=0; f[now][1]=1; state[now][1]=0; total[now]=1; for (int i=1;i<=n;i++) { for (int j=1;j<=total[now];j++) state[now][j]<<=2; for (int j=1;j<=m;j++) { pre=now,now=pre^1; memset(f[now],0,sizeof(f[now])); total[now]=0; tot=0; memset(h,0,sizeof(h)); for (int k=1;k<=total[pre];k++) { int s=state[pre][k]; int num=f[pre][k]; if (!num) continue; int p=(s>>bit[j-1])%4,q=(s>>bit[j])%4; if (!a[i][j]) { if (!p&&!q) Solve(s,num); } else if (!p&&!q) { if (a[i][j+1]) Solve(s+(1<<bit[j]),num); if (a[i+1][j]) Solve(s+(1<<bit[j-1]),num); if (a[i][j+1]&&a[i+1][j]) Solve(s+(1<<(bit[j-1]+1))+(1<<(bit[j]+1)),num); } else if (p&&q) { if (p==1&&q==1) { s=s-(1<<bit[j-1])-(1<<bit[j]); Solve(s,num); } } else if (!q) { if (p==1) { s=s-(1<<bit[j-1]); if (a[i+1][j]) Solve(s+(1<<(bit[j-1]+1)),num); if (a[i][j+1]) Solve(s+(1<<bit[j]),num); } else { s=s-(1<<(bit[j-1]+1)); Solve(s,num); if (a[i][j+1]) Solve(s+(1<<(bit[j]+1)),num); } } else { if (q==1) { s=s-(1<<bit[j]); if (a[i][j+1]) Solve(s+(1<<(bit[j]+1)),num); if (a[i+1][j]) Solve(s+(1<<bit[j-1]),num); } else { s=s-(1<<(bit[j]+1)); Solve(s,num); if (a[i+1][j]) Solve(s+(1<<(bit[j-1]+1)),num); } } } } } } int main() { for (int i=0;i<=100;i++) bit[i]=i<<1; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%s",s+1); for (int j=1;j<=m;j++) if (n<m) a[j][i]=s[j]=='_'; else a[i][j]=s[j]=='_'; } if (n<m) swap(n,m); Plugdp(); cout<<f[now][1]<<endl; return 0; }
感悟:
1.wa是没有清空f[now]数组
2.根据题目要求改变插头的含义
原文地址:http://blog.csdn.net/regina8023/article/details/44838887