bzoj 2331: [SCOI2011]地板 插头DP
2331: [SCOI2011]地板
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 541 Solved: 239
[Submit][Status]
Description
lxhgww的小名叫“小L”,这是因为他总是很喜欢L型的东西。小L家的客厅是一个的矩形,现在他想用L型的地板来铺满整个客厅,客厅里有些位置有柱子,不能铺地板。现在小L想知道,用L型的地板铺满整个客厅有多少种不同的方案?
需要注意的是,如下图所示,L型地板的两端长度可以任意变化,但不能长度为0。铺设完成后,客厅里面所有没有柱子的地方都必须铺上地板,但同一个地方不能被铺多次。
Input
输入的第一行包含两个整数,R和C,表示客厅的大小。
接着是R行,每行C个字符。’_’表示对应的位置是空的,必须铺地板;’*’表示对应的位置有柱子,不能铺地板。
Output
输出一行,包含一个整数,表示铺满整个客厅的方案数。由于这个数可能很大,只需输出它除以20110520的余数。
Sample Input
2 2
*_
__
*_
__
Sample Output
1
HINT
R*C<=100
太久没做插头DP,一来就把R*C<=100看成R,C<=100,这道题主要问题还是在数据范围里面,交wa了一次,因为我默认R最大为10,而实际上R可以取到100.
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MOD 20110520 #define MAXN 12 #define MAXV 531442 #define gv(x,ps) ((x)/p[(ps)]%3) #define cd(x,ps) ((x)-((x)/p[ps]%3*p[ps])) #define sd(x,ps,v) ((x)+v*p[ps]) int n,m; void pm(int x) { int i; for (i=0;i<=m;i++) { printf("%d",x%3); x/=3; } printf("\n"); } void deal(int &x,int y) { x=(x+y)%MOD; } char mp[104][104]; int dp[2][12][MAXV]; int p[12]; int main() { freopen("input.txt","r",stdin); int i,j,k,x,y,z; p[0]=1; scanf("%d%d\n",&n,&m); for (i=1;i<12;i++) p[i]=p[i-1]*3; for (i=0;i<n;i++) { for (j=0;j<m;j++) { scanf("%c",&mp[i][j]); } scanf("\n"); } int l; if (n<m) { for (i=0;i<max(n,m);i++) { for (j=i+1;j<max(n,m);j++) { swap(mp[i][j],mp[j][i]); } } swap(n,m); } l=p[m+1]; dp[0][0][0]=1; int v; for (i=0;i<n;i++) { for (j=0;j<m;j++) { if (j==m-1)//{{{ { if (mp[i][j]=='*') { for (k=0;k<l;k++) { if (!dp[i&1][j][k])continue; x=gv(k,j); y=gv(k,j+1); if (x||y)continue; deal(dp[(i+1)&1][0][k*3],dp[i&1][j][k]); } memset(dp[i&1],0,sizeof(dp[i&1])); }else { for (k=0;k<l;k++) { if (!dp[i&1][j][k])continue; x=gv(k,j); y=gv(k,j+1); v=cd(k,j); v=cd(v,j+1); if (x==0 && y==0) { z=sd(v,j,1); deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); }else if (x==0 && y==1) { z=sd(v,j,1); deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); }else if (x==0 && y==2) { z=sd(v,j,2); deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); z=v; deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); }else if (x==1 && y==0) { z=sd(v,j,2); deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); }else if (x==1 && y==1) { z=v; deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); }else if (x==1 && y==2) { //DO nothing }else if (x==2 && y==0) { z=v; deal(dp[(i+1)&1][0][z*3],dp[i&1][j][k]); }else if (x==2 && y==1) { //Do nothing }else if (x==2 && y==2) { //Do nothing } } memset(dp[i&1],0,sizeof(dp[i&1])); } }else//}}} { if (mp[i][j]=='*') { for (k=0;k<l;k++) { if (!dp[i&1][j][k])continue; x=gv(k,j); y=gv(k,j+1); if (x||y)continue; deal(dp[i&1][j+1][k],dp[i&1][j][k]); } }else { for (k=0;k<l;k++) { if (!dp[i&1][j][k])continue; x=gv(k,j); y=gv(k,j+1); v=cd(k,j); v=cd(v,j+1); if (x==0 && y==0) { z=sd(v,j+1,1); deal(dp[i&1][j+1][z],dp[i&1][j][k]); z=sd(v,j,1); deal(dp[i&1][j+1][z],dp[i&1][j][k]); z=sd(v,j+1,2); z=sd(z,j,2); deal(dp[i&1][j+1][z],dp[i&1][j][k]); }else if (x==0 && y==1) { z=sd(v,j+1,2); deal(dp[i&1][j+1][z],dp[i&1][j][k]); z=sd(v,j,1); deal(dp[i&1][j+1][z],dp[i&1][j][k]); }else if (x==0 && y==2) { z=v; deal(dp[i&1][j+1][z],dp[i&1][j][k]); z=sd(v,j,2); deal(dp[i&1][j+1][z],dp[i&1][j][k]); }else if (x==1 && y==0) { z=sd(v,j+1,1); deal(dp[i&1][j+1][z],dp[i&1][j][k]); z=sd(v,j,2); deal(dp[i&1][j+1][z],dp[i&1][j][k]); }else if (x==1 && y==1) { z=v; deal(dp[i&1][j+1][z],dp[i&1][j][k]); }else if (x==1 && y==2) { //Do nothing }else if (x==2 && y==0) { z=sd(v,j+1,2); deal(dp[i&1][j+1][z],dp[i&1][j][k]); z=v; deal(dp[i&1][j+1][z],dp[i&1][j][k]); }else if (x==2 && y==1) { //Do nothing }else if (x==2 && y==2) { //Do nothing } } } } } } cout<<dp[n&1][0][0]<<endl; return 0; }
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载
本博客已停用,新博客地址:http://mhy12345.xyz