bzoj2331: [SCOI2011]地板
来源:互联网 发布:svs视频分享网站seo 编辑:程序博客网 时间:2024/04/26 06:04
2331: [SCOI2011]地板
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 1298 Solved: 556
[Submit][Status][Discuss]
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的好题啊————对于我来说
第一次做这种变形。。
以前都是什么回路什么的
其实这题和别的也差不多。。
但插头的意义要改一下
0表示无插头,1表示有插头没有拐弯,2表示有插头且已经拐弯
但由于我之前的插P哈希模板是学习TYB大佬的,有点慢,TYB大佬也说不行了,于是改进了一下模板,运用了邻接表,就快多了。。前排膜拜TYB大佬
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int N=105;const int mod=100037;const int MOD=20110520;int r,c;bool map[N][N];int xx,yy;void init (){ memset(map,false,sizeof(map)); scanf("%d%d",&r,&c); for (int u=1;u<=r;u++) { char ss[105]; scanf("%s",ss+1); for (int i=1;i<=c;i++) { if (ss[i]=='_') { if (r<c)//将来要交换的啦 map[i][u]=true,xx=i,yy=u; else map[u][i]=true,xx=u,yy=i; } } } if (r<c) swap(r,c);}int sta[2][mod*10],num[2],list[2][mod*10],now;int last[mod+10],len=0;struct Edge{int y,next;}e[210000];int get(int s,int p){return (s>>((p-1)*2))&3;}void change(int &s,int p,int v){ s^=get(s,p)<<((p-1)*2); s^=(v)<<((p-1)*2);}void add(int st,int sum) { int x=st%mod; for(int i=last[x];i;i=e[i].next) if(list[now][e[i].y]==st) { sta[now][e[i].y]+=sum; sta[now][e[i].y]%=MOD; return; } num[now]++; list[now][num[now]]=st; sta[now][num[now]]=sum; int t=++len; e[t].y=num[now],e[t].next=last[x],last[x]=t; }int ans=0;void solve (){ now=0;sta[0][1]=1;num[0]=1;list[0][1]=0; for (int u=1;u<=r;u++) { for (int i=1;i<=c;i++) { now^=1; num[now]=0;len=0; memset(last,0,sizeof(last)); for (int k=1;k<=num[now^1];k++) { int st=list[now^1][k]; int sum=sta[now^1][k]; int p=get(st,i),q=get(st,i+1); if (u==xx&&i==yy)//已经到达“终点”了 { if (p+q==2)//这里有三种情况-->1.p=q=1,表示在这个点连起来 2.p=0,q=2,表示上面下来 3.和2反过来 { ans=ans+sum; ans%=MOD; } continue; } else if (map[u][i]==false) { if (p+q==0)//这里就是两个0啦 add(st,sum); continue; } else if (p+q==0) { int st2=st; if (map[u+1][i]) change(st2,i,1),add(st2,sum); st2=st; if (map[u][i+1]) change(st2,i+1,1),add(st2,sum); st2=st; if (map[u][i+1]&&map[u+1][i]) change(st2,i,2),change(st2,i+1,2),add(st2,sum); } else if (p==0&&q!=0) { int st2=st; if (q==1) { if (map[u+1][i]) change(st2,i,1),change(st2,i+1,0),add(st2,sum); st2=st; if (map[u][i+1]) change(st2,i+1,2),add(st2,sum); } else { if (map[u+1][i]) change(st2,i,2),change(st2,i+1,0),add(st2,sum); st2=st; change(st2,i+1,0);add(st2,sum); } } else if (p!=0&&q==0) { int st2=st; if (p==1) { if (map[u][i+1]) change(st2,i,0),change(st2,i+1,1),add(st2,sum); st2=st; if (map[u+1][i]) change(st2,i,2),add(st2,sum); } else { if (map[u][i+1]) change(st2,i,0),change(st2,i+1,2),add(st2,sum); st2=st; change(st2,i,0);add(st2,sum); } } else if (p==1&&q==1) { change(st,i,0);change(st,i+1,0); add(st,sum); } } } for (int k=1;k<=num[now];k++) list[now][k]<<=2; }}int main(){ init(); solve(); printf("%d\n",ans); return 0;}
阅读全文
0 0
- [bzoj2331][SCOI2011]地板
- BZOJ2331 [SCOI2011]地板
- BZOJ2331: [SCOI2011]地板
- 【SCOI2011】bzoj2331 地板
- bzoj2331: [SCOI2011]地板
- 【bzoj2331】[SCOI2011]地板 插头dp
- Bzoj2331[SCOI2011]地板:插头dp
- [插头DP] BZOJ2331 && SCOI2011 地板
- 【BZOJ 2331】 [SCOI2011]地板
- 2331: [SCOI2011]地板
- 2331: [SCOI2011]地板
- BZOJ 2331 [SCOI2011]地板
- ☆【动态规划】【SCOI2011】地板
- BZOJ 2331 SCOI2011 地板 插头DP
- [BZOJ]2331: [SCOI2011]地板 插头DP
- 硬木地板
- [scoi2011]糖果
- SCOI2011 糖果
- 【备忘】2017最新python教程老男孩Python14期视频教程下载
- 个人与企业的关系
- chrome调试js
- hdu-5446(中国剩余定理+lucas)
- opencv3学习之图像分割和尺寸调整(金字塔/resize)
- bzoj2331: [SCOI2011]地板
- JAVA 中BIO,NIO,AIO的理解
- POJ3468 A Simple Problem with Integers (线段树区间更新)
- js实现回车键换下一行
- MyEclipse中常用的快捷键
- 解决Controller接受到的参数乱码
- PHP获取当前月与上个月的月初及月末时间戳的方法
- js学习笔记之继承
- maven入门及使用myeclipse构建maven项目