poj 3254(状态压缩DP)
poj 3254(状态压缩DP)
题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
解析:根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛。首先很容易看到,每一行的状态要符合牧场的硬件条件,即牛必须放在能放牧的方格上。这样就能排除一些状态。另外,牛与牛之间不能相邻,这样就要求每一行中不能存在两个相邻的1,这样也能排除很多状态。然后就是根据上一行的状态转移到当前行的状态的问题了。必须符合不能有两个1在同一列(两只牛也不能竖着相邻)的条件。这样也能去掉一些状态。第i行为某状态state时的方案数为第i-1行的所有符合条件的状态的方案数的总和。
状态表示:dp[state][i]:在状态为state时,到第i行符合条件的可以放牛的方案数
状态转移方程:dp[state][i] =Sigma dp[state'][i-1] (state'为符合条件的所有状态)
DP边界条件:首行放牛的方案数dp[state][1] =1(state符合条件) OR 0 (state不符合条件)
利用位运算可以巧妙的判断某些状态是否符合条件:
if(a&(a<<1)==1),用于判断a中相邻位是否同为1,等式成立表示存在,否则不存在;
if(a&b),用于判断a和b相同位是否同为1,等式成立表示存在,否则不存在。
AC代码如下:
#include<stdio.h>
#define M 100000000
int dp[][<<],state[<<],cur[];
int m,n,top=;
void init() //预处理所有满足条件(相邻位置不能放牛)的状态
{
int i,sum=<<n;
for(i=;i<sum;i++)
if(i&(i<<))
continue;
else
state[top++]=i;
}
int fit(int a,int b) //判断二进制数相同位置是否同为1
{
if(a&b)
return ;
return ;
}
void DP()
{
int i,j,k;
for(i=;i<top;i++) //初始化第一行
if(fit(state[i],cur[]))
dp[][i]=;
for(i=;i<=m;i++)
for(j=;j<top;j++) //遍历第i行所有状态
{
if(!fit(cur[i],state[j])) //若该状态不符合条件
continue;
else
{
for(k=;k<top;k++) //遍历第i-1行所有状态,找出满足条件的
{
if(!fit(state[k],cur[i-])) //这一句其实不用也可以
continue;
if(!fit(state[k],state[j])) //若相邻位置同为1,不符合条件
continue;
dp[i][j]=(dp[i][j]+dp[i-][k])%M; //dp[state][i] =Sigma dp[state'][i-1] (state'为符合条件的所有状态)
}
}
}
int ans=;
for(i=;i<top;i++) //求最后一行所有满足条件的状态
ans=(ans+dp[m][i])%M;
printf("%d\n",ans);
}
int main()
{
int x,i,j;
scanf("%d%d",&m,&n);
for(i=;i<=m;i++)
for(j=;j<=n;j++)
{
scanf("%d",&x);
if(x==) //如果该位置不能放牛,则将该行变成相应的二进制数,方便判断
cur[i]+=<<(n-j);
}
init();
DP();
return ;
}
poj 3254(状态压缩DP)的更多相关文章
- poj 3254 状态压缩DP
思路:把每行的数当做是一个二进制串,0不变,1变或不变,找出所有的合法二进制形式表示的整数,即相邻不同为1,那么第i-1行与第i行的状态转移方程为dp[i][j]+=dp[i-1][k]: 这个方程得 ...
- POJ 3254 状态压缩 DP
B - Corn Fields Crawling in process... Crawling failed Time Limit:2000MS Memory Limit:65536KB ...
- poj 3254(状态压缩+动态规划)
http://poj.org/problem?id=3254 题意:有一个n*m的农场(01矩阵),其中1表示种了草可以放牛,0表示没种草不能放牛,并且如果某个地方放了牛,它的上下左右四个方向都不能放 ...
- POJ 1185 状态压缩DP(转)
1. 为何状态压缩: 棋盘规模为n*m,且m≤10,如果用一个int表示一行上棋子的状态,足以表示m≤10所要求的范围.故想到用int s[num].至于开多大的数组,可以自己用DFS搜索试试看:也可 ...
- POJ 1185 状态压缩DP 炮兵阵地
题目直达车: POJ 1185 炮兵阵地 分析: 列( <=10 )的数据比较小, 一般会想到状压DP. Ⅰ.如果一行10全个‘P’,满足题意的状态不超过60种(可手动枚举). Ⅱ.用DFS ...
- poj 2923(状态压缩dp)
题意:就是给了你一些货物的重量,然后给了两辆车一次的载重,让你求出最少的运输次数. 分析:首先要从一辆车入手,搜出所有的一次能够运的所有状态,然后把两辆车的状态进行合并,最后就是解决了,有两种方法: ...
- poj 2688 状态压缩dp解tsp
题意: 裸的tsp. 分析: 用bfs求出随意两点之间的距离后能够暴搜也能够用next_permutation水,但效率肯定不如状压dp.dp[s][u]表示从0出发訪问过s集合中的点.眼下在点u走过 ...
- Mondriaan's Dream(POJ 2411状态压缩dp)
题意:用1*2的方格填充m*n的方格不能重叠,问有多少种填充方法 分析:dp[i][j]表示i行状态为j时的方案数,对于j,0表示该列竖放(影响下一行的该列),1表示横放成功(影响下一列)或上一列竖放 ...
- poj 2411 状态压缩dp
思路:将每一行看做一个二进制位,那么所有的合法状态为相邻为1的个数一定要为偶数个.这样就可以先把所有的合法状态找到.由于没一层的合法状态都是一样的,那么可以用一个数组保存.由第i-1行到第i行的状态转 ...
- poj 3254 状态压缩
Corn Fields Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 15285 Accepted: 8033 Desc ...
随机推荐
- 大数据中HBase集群搭建与配置
hbase是分布式列式存储数据库,前提条件是需要搭建hadoop集群,需要Zookeeper集群提供znode锁机制,hadoop集群已经搭建,参考 Hadoop集群搭建 ,该文主要介绍Zookeep ...
- 快速稀疏角点光流框架(Fast sparse corner optical flow framework)
光流适用在连续的图像系列(视频流)中,描述本身或画面目标的运动状态:在目标跟踪.运动分析.甚至slam中都有广泛应用. opencv里就有不少光流算法,其中很经典也是当前被调用最多的的Lucas-Ka ...
- Python实现学生系统
# 4. 修改之前的学生信息管理程序,实现添加菜单和选择菜单操作功能: # 菜单: # +-----------------------------+ # | 1) 添加学生信息 | # | 2) 查 ...
- .Net MVC缓存
https://www.cnblogs.com/JoeSnail/p/7993903.html
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第7节: 获取异线程释放的对象
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第七节: 获取异线程释放的对象 上一小节分析了异线程回收对象, 原理是通过与stack关联的WeakOrder ...
- maven项目的标准目录结构
maven项目的标准目录结构如下:
- head和tail命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/amosli/p/3496027.html 当要查看上千行的大文件时,我们可不会用cat命令把整个文件内容给打印出来,相 ...
- lastlog命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/qiyebao/p/4331078.html last 显示所有用户最后登录信息(会显示系统用户) last -u 50 ...
- 精通Python爬虫-03-狩猎大师
声明: 本系列文章原创于慕课网,作者秋名山车神,任何人不得以任何形式在不经作者允许的情况下,进行任何形式的印刷以及销售,转载需注明出处及此声明. 本系列文章更新至少每周一更,将涉及Python爬虫基础 ...
- java浮点数存储
转自: [解惑]剖析float型的内存存储和精度丢失问题 1.小数的二进制表示问题 首先我们要搞清楚下面两个问题: (1) 十进制整数如何转化为二进制数 算法很简单.举个例子,11表示成二进制数: ...