(POJ 3254)Corn Fields <状态压缩DP 好题>

来源:互联网 发布:迅捷贝软件 编辑:程序博客网 时间:2024/06/02 02:36

Corn Fields
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
Hint

Number the squares as follows:
1 2 3
4

There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.
Source

USACO 2006 November Gold

题意:
有n*m大的一个地方,1表示土地肥沃可以种植物,0表示不能种植物,问:在不许有两个植物相邻的情况下,有多少种放置的方法。

分析:
刚开始做状压DP的题,对于这题而言我只能想到超时的DFS。
看了这边博客才搞懂的:http://blog.csdn.net/mengxiang000000/article/details/51075506
但是我也是啃了一个小时才完全搞懂。下面是我自己根据这篇博客做的思路整理

首先对于一个12*12的网格,每一行的选择可以有很多,为了方便表示出每一行选择的状态,我们将每一行压缩在一个int中,每一位二进制表示一个格子的状态(1,0)。
比如样例1变成了a[2] = {7,2}
然后题目要求没有两个所选的格子有相邻的边。我们从第一行开始往下依次选出每行可选的所有情况,那么我们只需要注意两点即可:(比如我们再选第i行)
1:第i行所选的格子一定是a[i]中二进制为1的位置的子集,并且没有1相邻。
2:第i行和第i-1行没有相邻的1被同时选中。

对于条件1:
判断(i,j)是否合法,首先我们知道,j的状态和第i行土地的状态的0的位子是一定相同的,但是j的1可以比土地的少,我们举例说明:
假设土地的状态值为5:1 0 1,我们合法的j放置状态有: 1 0 0 / 1 0 1 /0 0 1
对于土地状态我们对合法j放置状态进行&运算有:

  1 0 1& 1 0 0----------------  1 0 0   1 0 1& 1 0 1------------------  1 0 1  1 0 1& 0 0 1-----------------  0 0 1

我们发现,如果是合法的放置状态,我们用土地的状态值&j的状态值的结果一定等于j。辣么我们对于j是否合法的第一个判断就要这样写(反例大家随便写一个就发现确实不等于j):
if(a[i]&j!=j)return 0;
对于另外一个需要判断的条件:同一行不能有两个相邻的1,解决的方法就是在2进制01串的末尾加上一个0之后和原来的01串进行&运算,如果结果为0,合法,否则不合法,
我们也举例说明:

       1 0 1   & 1 0 1 0---------------------     0 0 0 0合法    1 1 0& 1 1 0 0----------------------  0 1 0 0不合法

对于这两个判断我们已经了解如何操作,然后我们再用代码来实现:

int judge(int x,int y){    if((a[x] & y) != y) return 0; // 判断是第i行可取的子集    if((y & (y<<1)) != 0) return 0; //判断没有相邻的1    return 1;}

对于条件2:
只要 (j & k) == 0 那么就满足条件

对于所有满足条件的k我们就知道从i-1行的k状态可以到达第i行的j状态,即dp[i-1][k] ->dp[i][j],我们记录所有到达dp[i][j]状态的数目。那么dp[n][i]的和即为我们所要求的解。

对于样例dp[][]的所有状态如下:
这里写图片描述

整体dp思路和01背包一样

AC代码:

#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define mod 100000000int n,m,a[15];int dp[13][1<<13];int judge(int x,int y){    if((a[x] & y) != y) return 0; // 判断是第i行可取的子集    if((y & (y<<1)) != 0) return 0; //判断没有相邻的1    return 1;}void solve(){    memset(dp,0,sizeof(dp));    dp[0][0] = 1;  // 初始化    for(int i=1;i<=n;i++)    {        for(int j=0;j<(1<<m);j++) //判断在第i行放置j这种状态的牛是否合法        {            if(judge(i,j)==0) continue;            for(int k=0;k<(1<<m);k++) //找出所有第i-1行和第i行不冲突的状态            {                if((j&k) != 0) continue; //判断是否冲突                dp[i][j] += dp[i-1][k];                dp[i][j] %= mod;            }        }    }    int ans = 0;    for(int i=0;i<(1<<m);i++)    {        ans += dp[n][i];        ans %= mod;    }    printf("%d\n",ans);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        int k;        for(int i=1;i<=n;i++)        {            a[i] = 0;            for(int j=1;j<=m;j++)            {                scanf("%d",&k);                a[i] = (a[i]<<1) + k; //转化为2进制表示            }        }        solve();    }    return 0;}
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 新手驾照扣6分怎么办 a2驾驶证逾期未审验怎么办 c1驾照扣了6分怎么办 b1驾照被扣12分怎么办 b2驾驶本扣分了怎么办 驾驶本扣9分后怎么办 b1照扣12分怎么办 b2扣了15分怎么办 b2有扣分未年审怎么办 b2驾驶证扣4分怎么办 b2驾驶证扣10分怎么办 刚发驾驶证照片太丑想换怎么办! 考驾照时户口变更怎么办 驾照年审色盲未过怎么办 考驾驶证互联网注册号码怎么办 驾驶证体检视力不过关怎么办 六年驾照满了怎么办 驾照扣了40多分怎么办 一个驾照扣24分怎么办 南昌电动车牌照丢了怎么办 上海餐饮工作人员怎么办健康证 房产过户没有遗嘱公证怎么办 在外地被扣12分怎么办 公务员体检视力不过关怎么办弱视 身份证被盗用注册公司怎么办 驾照分卖了12分怎么办 一年12分扣完了怎么办 滴滴车管所信息不同步怎么办 驾驶证过期两个月了怎么办 科目二考试第一次不合格怎么办 科目二不想考了怎么办 科二有事考不了怎么办 科四有事去不了怎么办 社保卡发了密码怎么办 不知道社保卡号怎么办 科目三未到30天怎么办 户口地址变了驾照怎么办 拿了驾照没开车怎么办 免检的车在外地怎么办 2018年b2证扣3分怎么办 科一考试没去怎么办