PKU 3254 状态压缩DP
2011-08-11 23:37
232 查看
http://poj.org/problem?id=3254
题意:输入一个n*m的矩阵,矩阵由数字0和1组成,0表示不能种植玉米的草地,1表示能够种植玉米的草地。然后在种植了玉米的草地上放牛,放牛的数目随意,但是要满足相邻的草地间不能同时放牛,要求所有放牛的方案总数。
例如:
2 3
1 1 1
0 1 0
方案总数为9,因为将每块草地编号后得到
1 2 3
0 4 0
一头都不放有1种情况,放一头牛的方案为1,2,3,4都行,有4种,放两头牛的方案有(1,3) (1 4) (3 4),有3中,放三头牛的方案有(1,3,4)一种,一共9种!
分析:地图显然是0和1构成,即用0,1来表示所有的情况,所以显然是二进制的情况,即用二进制来表示所有情况的一种题型。
我们可以使用二进制的状态压缩,用一个数来表示某一行的放牛情况,例如某一行的放牛方案为5,而五的二进制表示为1 0 1,对于上面的数据来说,相邻的没有放牛,并且放牛的地方都有种植玉米,所以这是一种可行的方案。那么第一行到底有多少可行的方案呢,由于相邻的玉米间不许放牛,不难看出有
(0,0,0)[0] 、 (1,0,0)[4] 、 (0,1,0)[2] 、 (0,0,1)[1] 、 (1,0,1)[5]
再看第二行,它的所有方案为
(0,0,0)[0] 、 (0,1,0)[2]
现在状态压缩已经完毕,我们要开始动规,动规是从第一行一直到最后一行。
我们开设数组dp[i][j],表示第i行取第j种状态的所有可行方案总数。
看上面的数据,第一行取0,4,2,1,5五种状态中的一种都只有一种情况,所有dp[1][i]=1.(i=1,2,3,4,5)。
再看第二行的第一种状态0,如果第二行取了0的话,也就是说第二行不放牛,那么第二行和第一行的任何一种状态都不矛盾(上下相邻的不能放牛),那么第一行的所有情况都可以取到,于是dp[2][1]=5。
再看第二个状态2.,如果取了2的话,那么第二行将和第一行的状态2发生矛盾,即放牛情况为
0 1 0
0 1 0
很显然的看到上下相邻了,所以第二行的状态2只能和第一行的状态0,4,1,5共存,即dp[2][2]=4。
最后我们将最后一行的所有状态的dp值相加,便得到了我们要求的答案~~dp[2][1]+dp[2][2]=5+4=9
View Code
题意:输入一个n*m的矩阵,矩阵由数字0和1组成,0表示不能种植玉米的草地,1表示能够种植玉米的草地。然后在种植了玉米的草地上放牛,放牛的数目随意,但是要满足相邻的草地间不能同时放牛,要求所有放牛的方案总数。
例如:
2 3
1 1 1
0 1 0
方案总数为9,因为将每块草地编号后得到
1 2 3
0 4 0
一头都不放有1种情况,放一头牛的方案为1,2,3,4都行,有4种,放两头牛的方案有(1,3) (1 4) (3 4),有3中,放三头牛的方案有(1,3,4)一种,一共9种!
分析:地图显然是0和1构成,即用0,1来表示所有的情况,所以显然是二进制的情况,即用二进制来表示所有情况的一种题型。
我们可以使用二进制的状态压缩,用一个数来表示某一行的放牛情况,例如某一行的放牛方案为5,而五的二进制表示为1 0 1,对于上面的数据来说,相邻的没有放牛,并且放牛的地方都有种植玉米,所以这是一种可行的方案。那么第一行到底有多少可行的方案呢,由于相邻的玉米间不许放牛,不难看出有
(0,0,0)[0] 、 (1,0,0)[4] 、 (0,1,0)[2] 、 (0,0,1)[1] 、 (1,0,1)[5]
再看第二行,它的所有方案为
(0,0,0)[0] 、 (0,1,0)[2]
现在状态压缩已经完毕,我们要开始动规,动规是从第一行一直到最后一行。
我们开设数组dp[i][j],表示第i行取第j种状态的所有可行方案总数。
看上面的数据,第一行取0,4,2,1,5五种状态中的一种都只有一种情况,所有dp[1][i]=1.(i=1,2,3,4,5)。
再看第二行的第一种状态0,如果第二行取了0的话,也就是说第二行不放牛,那么第二行和第一行的任何一种状态都不矛盾(上下相邻的不能放牛),那么第一行的所有情况都可以取到,于是dp[2][1]=5。
再看第二个状态2.,如果取了2的话,那么第二行将和第一行的状态2发生矛盾,即放牛情况为
0 1 0
0 1 0
很显然的看到上下相邻了,所以第二行的状态2只能和第一行的状态0,4,1,5共存,即dp[2][2]=4。
最后我们将最后一行的所有状态的dp值相加,便得到了我们要求的答案~~dp[2][1]+dp[2][2]=5+4=9
View Code
#include<iostream> #include<string> using namespace std; #define maxn (1<<12) int map[14][14]; int dp[14][maxn+2]; int n,m,i,j; void dfs(int k,int state) //所有状态顺序都是从右往左,即k的增加说明了状态在向左进位 { if(k==m) { dp[i+1][state]+=dp[i][j]; return; } if(!map[i+1][m-k-1]) //没有玉米 { dfs(k+1,state); //状态保持不变 } else { if(((j>>k)&1)==0) { if(k==0) dfs(k+1,state|1<<k); //该位置k放了牛,则state在k位上加1 if(k-1>=0 && ((state>>(k-1))&1)==0) //并且它右边相邻的地里没有放牛 dfs(k+1,state|1<<k); //同上 } dfs(k+1,state); } } int main() { freopen("D:\\in.txt","r",stdin); while(scanf("%d%d",&n,&m)!=EOF) { for(i=1;i<=n;i++) { for(j=0;j<m;j++) { scanf("%d",&map[i][j]); } } memset(dp,0,sizeof(dp)); dp[0][0]=1; //地图是从1到n,这里人工的将地图扩大一行,第零行一个玉米都不种,这样便有了初始值,又不影响接下来的搜索 for(i=0;i<n;i++) //注意i,j是全局变量,j便是第i行的状态 { for(j=0;j<(1<<m);j++) { if(dp[i][j]) { dfs(0,0); //对i+1行进行DP,可达的所有状态dp[i+1][j]都将加上dp[i][j] } } } int ans=0; for(i=0;i<(1<<m);i++) { ans=(ans+dp [i])%100000000; } printf("%d\n",ans); } return 0; }
相关文章推荐
- poj 3254 Corn Fields_状态压缩dp
- [状态压缩DP] Poj 3254, Poj 1185
- poj 3254 Corn Fields (状态压缩DP)
- POJ 3254 Corn Fields(状态压缩DP)
- 状态压缩DP 入门 POJ 3254
- 两道状态压缩DP-- POJ 3254,HDU 1074
- pku 1691 Painting A Board 状态压缩dp
- POJ 3254 Corn Fields(状态压缩DP)
- POJ 3254(状态压缩dp)
- poj 3254 Corn Fields 状态压缩dp
- poj 3254 Corn Fields_状态压缩dp
- poj3254 状态压缩dp
- POJ 3254 Corn Fields 状态压缩DP
- POJ-3254 Corn Fields 状态压缩DP+滚动数组
- POJ 3254 (基础 状态压缩 DP )
- POJ 3254 Corn Fields (状态压缩DP)
- pku 2288 Islands and Bridges(状态压缩DP)
- poj 3254 状态压缩dp
- POJ 3254 Corn Fields 状态压缩dp入门
- poj 3254 状态压缩DP