poj 3250 状态压缩dp入门

Corn Fields

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7798   Accepted: 4159

Description

Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can‘t be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.

Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.

Input

Line 1: Two space-separated integers: M and N 
Lines 2..M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)

Output

Line 1: One integer: the number of ways that FJ can choose the squares modulo 100,000,000.

Sample Input

2 3
1 1 1
0 1 0

Sample Output

9
 1 #include<iostream>
 2 #include<string>
 3 #include<cstdio>
 4 #include<vector>
 5 #include<queue>
 6 #include<stack>
 7 #include<set>
 8 #include<algorithm>
 9 #include<cstring>
10 #include<stdlib.h>
11 #include<math.h>
12 #include<map>
13 using namespace std;
14 #define pb push_back
15 #define ll long long
16 #define mod 100000000
17 int dp[20][1<<13],p[20][20];
18 int can(int x){//   相邻两位是否相同
19     if(x&(x<<1)) return 0;
20     else return 1;
21 }
22 int main(){
23     int n,m;
24     while(cin>>n>>m){
25         int mmax=(1<<m)-1;
26         for(int i=1;i<=n;i++)
27             for(int j=1;j<=m;j++)
28             cin>>p[i][j];
29         memset(dp,0,sizeof(dp));
30         dp[0][0]=1;
31         for(int i=1;i<=n;i++){
32             int tmp=0;
33             for(int j=1;j<=m;j++)
34             if(!p[i][j]) tmp+=(1<<(j-1));//tmp存的是不能放牛的最大状态的值
35             for(int j=0;j<=mmax;j++){
36                 if(j&tmp) continue;//因为j的某些位与tmp中一些位置相同,但是tmp中的是不能放牛的,所以排除
37                 if(!can(j)) continue; //有相邻的位置放牛,所以排除
38                 for(int k=0;k<=mmax;k++)
39                 if(dp[i-1][k]&&!(j&k))//排除与上一行相邻的
40                 dp[i][j]=(dp[i][j]+dp[i-1][k])%mod;
41             }
42         }
43         ll ans=0;
44         for(int i=0;i<=mmax;i++) ans=(ans+dp[n][i])%mod;
45         cout<<ans<<endl;
46     }
47 }
				
时间: 2024-10-11 17:15:56

poj 3250 状态压缩dp入门的相关文章

Hdu-1565 方格取数(1) (状态压缩dp入门题

方格取数(1) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4702    Accepted Submission(s): 1782 Problem Description 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出

hoj 2662 Pieces Assignment 状态压缩dp入门

//hoj 2662 Pieces Assignment //有一个n*m的棋盘(n.m≤80,n*m≤80)要在棋盘上放k(k≤20)个棋子,使得任意两 //个棋子不相邻(每个棋子最多和周围4个棋子相邻).求合法的方案总数. // //算是另一个状态压缩dp入门吧 //dp[i][S][j]表示第i行的棋子状态是S(整数的二进制形式,比如5为 // ...101,省略号表示前导0,那一位上是1就表示哪一列上放了棋子,5表示第一列 //第三列放了棋子.)时已经放了j颗棋子,则转移方程为: //d

Mondriaan&#39;s Dream(POJ 2411状态压缩dp)

题意:用1*2的方格填充m*n的方格不能重叠,问有多少种填充方法 分析:dp[i][j]表示i行状态为j时的方案数,对于j,0表示该列竖放(影响下一行的该列),1表示横放成功(影响下一列)或上一列竖放成功.状态转移时,枚举每一行可能的状态上一行取反得下一行能放的状态. #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include &

状态压缩dp入门 第一题 POJ 3254 Corn Fields

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6460   Accepted: 3436 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yumm

状态压缩dp入门 (poj3254 Corn Fields)

题目链接:http://poj.org/problem?id=3254 题意:给出一个n行m列的草地,1表示肥沃,0表示贫瘠,现在要把一些牛放在肥沃的草地上,但是要求所有牛不能相邻,问你有多少种放法. 分析:假如我们知道第 i-1 行的所有的可以放的情况,那么对于第 i 行的可以放的一种情况,我们只要判断它和 i - 1 行的所有情况的能不能满足题目的所有牛不相邻,如果有种中满足,那么对于 i 行的这一中情况有 x 中放法. 前面分析可知满足子状态,我们我们确定可以用dp来解决. 但是我们又发现

动态规划之状态压缩dp入门

状态压缩动态规划(简称状压dp)是另一类非常典型的动态规划,通常使用在NP问题的小规模求解中,虽然是指数级别的复杂度,但速度比搜索快,其思想非常值得借鉴. 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.'&'符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.'|'符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.'^'符号,x^y

Poj 1185 炮兵阵地(状态压缩dp 入门题)

炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17272   Accepted: 6593 Description 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用"H" 表示),也可能是平原(用"P"表示),如下图.在每一格平原地形上最多可以布置一支炮兵部队(山地上不能够部署炮兵部队):一支炮兵部队在地图上的攻击

POJ 3311 状态压缩DP

题意:求从0点走到所有点又走回来的最短距离 该题又很多做法,我用的是弗洛伊德+状态压缩 先遍历所有点,求出两点间最短的距离,而后用状态压缩表示该点是否走过,(1<<n)-1则表示所有点都走过. 附AC代码 #include<stdio.h> #include<string.h> int map[12][12]; int dp[(1<<12)+1][12]; int min1(int a,int b) { if(a<b) return a; return

状态压缩dp入门

poj1321 http://poj.org/problem?id=1321 我们可以把棋盘的每一行看做是一个状态,如果某一列放置了棋子,那么就标记为1,否则就标记为0.然后把它看成是一个二进制数,然后转为10进制数,就可以当做数组下标然后进行状态转移了 设dp[i][s] 为处理到第i行时,状态为s的方法数 那么我们枚举第i-1行的所有状态s dp[i][s] += dp[i-1][s]; //表示第i行不放置棋子的方法数 dp[i][s|(1<<j)] += dp[i-1][s] //表示