poj 2411| 插头dp
2015-11-16 10:39
190 查看
经典题: 用1*2的木板铺满n*m的矩形的方案数。做一下插头dp的模板。0表示这个位置不可以放木板(也就是已经放上了木板),1表示这个位置可以放木板(也就是没放木板)。转移有两种1.当前位置上方的格子如果没放,那么在这个格子放竖着的,如果放了,什么也不放2.当前位置上方放了,左面没放,那么可以放一个横着的。//别看代码长,大部分都是哈希表(虽然这道题用不到,以后呢?)
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define md #define ll long long #define inf (int) 1e9 #define eps 1e-8 #define N 5010 using namespace std; struct ha { int sz; int a ,q ; ll f ; void clear() { memset(a,-1,sizeof(a)); sz=0; } void insert(int x,ll d) { int pos=x%N; while (a[pos]!=-1&&a[pos]!=x) { pos++; if (pos>=N) pos-=N; } if (a[pos]==-1) { q[++sz]=pos; a[pos]=x; f[pos]=0; } f[pos]+=d; } ll find(int x) { int pos=x%N; while (a[pos]!=-1&&a[pos]!=x) { pos++; if (pos>=N) pos=N; } if (a[pos]==x) return f[pos]; else return 0; } } hash[2]; int get(int s,int p,int l=1) { if (p<=0) return 0; return (s>>((p-1)*l))&((1<<l)-1); } void set(int &s,int p,int d,int l=1) { s^=get(s,p)<<((p-1)*l); s|=d<<((p-1)*l); } int main() { int n,m,now,pre; while (1) { scanf("%d%d",&n,&m); if (n==0&&m==0) break; if ((n&1)&&(m&1)) { printf("0\n"); continue;} now=1,pre=0; hash[now].clear(); hash[pre].clear(); hash[now].insert(0,1); for (int i=1;i<=n;i++) { for (int j=1;j<=m;j++) { swap(now,pre); hash[now].clear(); for (int k=1;k<=hash[pre].sz;k++) { int pos=hash[pre].q[k]; int s=hash[pre].a[pos]; ll d=hash[pre].f[pos]; int p=get(s,j),q=get(s,j-1); int S=s; set(S,j,p^1); hash[now].insert(S,d); if (p==0&&q==1) { S=s; set(S,j-1,0); hash[now].insert(S,d); } } } } printf("%lld\n",hash[now].find(0)); } return 0; }
相关文章推荐
- bzoj 2660 最多的方案 | dp
- bzoj 3170 松鼠聚会 | 旋转坐标
- bzoj 1537 bus|cdq分治
- bzoj 2257 瓶子和燃料
- bzoj 3398 牡牛和牝牛
- bzoj 3534 重建
- bzoj 4017 小Q的无敌异或
- bzoj 1002 轮状病毒
- bzoj 3288 矩阵
- bzoj 4031 小z的房间
- bzoj 4004 装备购买
- 容斥原理
- 主席树&树状数组套主席树
- bzoj 3589 动态树
- bzoj 3622 已经没有什么好害怕的了
- 几种线程池的实现算法分析【转载】
- OC中的特有语法
- 搭建jenkins环境(linux操作系统)
- Codeforces Round #331 (Div. 2)
- java代码封装