POJ 2411 【基础状压DP】
2015-09-02 16:33
316 查看
给出的行列范围小,所以考虑状压。用0表示向下摆(摆到这一行的时候这个位置是空的),1表示这里有东西,可能是上一行放上来的,也可能是横着摆放的。
考虑怎么进行状态转移。对于当前状态,枚举所有的状态,找到符合条件的之前的状态。什么是之前的状态呢,如果当前行,某个位置出现0,那么上一行这个位置就绝对不能是0,如果某个位置是1,那么上一行是0或者1都可以。所以如果now|pre结果都是1111..那么就是符合条件的之前的状态。然后还要检查当前的状态是否是正确的状态,先从状态中去掉从上一行来的砖块,或者是要向下摆放的砖块,然后检查剩下的砖块中是否存在不连续的2个1,如果有,就不是符合条件的状态。
初始状态:dp[第0行][(1<<w)-1]=1; //第一行不能有来自上一行的砖头
结束状态:dp[最后一行][(1<<w)-1];
考虑怎么进行状态转移。对于当前状态,枚举所有的状态,找到符合条件的之前的状态。什么是之前的状态呢,如果当前行,某个位置出现0,那么上一行这个位置就绝对不能是0,如果某个位置是1,那么上一行是0或者1都可以。所以如果now|pre结果都是1111..那么就是符合条件的之前的状态。然后还要检查当前的状态是否是正确的状态,先从状态中去掉从上一行来的砖块,或者是要向下摆放的砖块,然后检查剩下的砖块中是否存在不连续的2个1,如果有,就不是符合条件的状态。
初始状态:dp[第0行][(1<<w)-1]=1; //第一行不能有来自上一行的砖头
结束状态:dp[最后一行][(1<<w)-1];
#include <stdio.h> #include <iostream> #include <string.h> using namespace std; #define maxn 2048 #define ll long long ll dp[2][maxn]; int check(int x) { int que[12],top=0; while(x) { que[top++]=x&1; x>>=1; } for(int i=0;i<top;i++) { if(!que[i]) continue; if(i+1<top&&que[i+1]) i++; else return 0; } return 1; } void work(int h,int w) { memset(dp,0,sizeof(dp)); dp[1][(1<<w)-1]=1; int cmp=(1<<w)-1; int flag; for(int i=0;i<h;i++) { flag=i&1; for(int now=0;now<=cmp;now++) { for(int pre=0;pre<=cmp;pre++) { if((now|pre)==cmp) { int tmp=now⪯ if(check(tmp)) dp[flag][now]+=dp[!flag][pre]; } } } memset(dp[!flag],0,sizeof(dp[!flag])); } cout<<dp[flag][cmp]<<endl; } int main() { int n,m; while(cin>>n>>m) { if(!n&&!m) break; work(n,m); } return 0; }
相关文章推荐
- 调试
- 使用HelloCharts开源图表库制作柱状图
- LCD控制器与驱动器
- Longest Substring Without Repeating Characters
- PhoneGap入门
- 【转】android 怎么随意摆放button的位置?
- 日志组件logback的介绍及配置使用方法
- EL表达式(Expression Language)
- 一个sql很多个not like的简化语句
- runtime 运行时机制 完全解读
- NYOJ 54 小明的存钱计划
- 用户控件添加贝塞尔 曲线不显示问题
- Struts2 part 3:在Action中使用ServletAPI
- 苹果的 CoreData
- 整数中1出现的次数(从1到n整数中1出现的次数)
- Win7脱机文件夹同步取消与功能屏蔽
- sql根据年月分组
- NYOJ 53 不高兴的小明
- Gearman1.1.12安装与启动
- Java____Eclipse下JUnit单元测试(中级)