poj3254 状压dp 每行独立 入门水题

Corn Fields

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 18789   Accepted: 9880

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

题意:给一个地图,1表示可用,0表示不可用,要求从里面任意选若干1,使得每个1不相邻(在地图里不共用一条边),求选的方法

首先,要取余。。。不能枚举,一看就像是dp,再其次,数据这么小,状态那么那么多,一看就是状压dp;

那么关键就是,怎么确定状态(初始化+每次判断);

这个可以直接参考代码注释了;

说一下新手踩的坑吧:

1.每次init的时候,nmax要在正好的范围,否则会wa(特意试了试,但是不知道为什么,如果只是与运算的话应该不会影响啊);

2.在读入地图的时候记得是反的啊!反的啊!反的啊!在不可行的点为1,在可行的点为0;

3.要用inline啊,用了之后从64ms变为32ms

上代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>

using namespace std;

const int Nmax = 1 << 13;
int dp[15][Nmax],map[15],sta[Nmax],snum,m,n;
const int MOD = 100000000;

void init(){
    int nmax = 1 << n;
    for(int i = 0;i < nmax;i++){
        if(!(i&(i << 1)))
            sta[snum++] = i;
    }
    return;
}

inline int fit(int cur_sta,int cur){
    return (!(sta[cur_sta]&map[cur]));
}

int main(){
    scanf("%d%d",&m,&n);
    init();
    int innum;
    for(int i = 0;i < m;i++){
        for(int j = 0;j < n;j++){
            scanf("%d",&innum);
            if(innum == 0)//不合法时才相加
            map[i] += 1<<(n-j-1);
        }
    }

    for(int i = 0;i < snum;i++){
        if(fit(i,0))
            dp[0][i] = 1;
    }

    for(int i = 1;i < m;i++){//当前是第几行
        for(int j = 0;j < snum;j++){//当前行的状态
            if(!fit(j,i))//当前状态可行
                continue;
            for(int k = 0;k < snum;k++){//上一行的状态
                if(!fit(k,i-1))
                    continue;
                if(sta[j]&sta[k])//为0时无冲突
                    continue;
                dp[i][j] = (dp[i][j] + dp[i-1][k])%MOD;
            }
        }
    }

    int sum = 0;
    for(int i = 0;i < snum;i++){
        sum = (sum + dp[m-1][i])%MOD;
    }
    printf("%d\n",sum);
    return 0;
}

原文地址:https://www.cnblogs.com/xuyanqd/p/9051604.html

时间: 2024-10-10 20:41:34

poj3254 状压dp 每行独立 入门水题的相关文章

POJ3254 状压DP入门

题目:http://poj.org/problem?id=3254 因为&运算写成&&--导致调试了快一个小时代的代码没有搞定 关于建图: 1.题目中是1表示可以放牧,0表示不可以放牧,但是建图的时候,可以放牧的位用0表示,不可以放牧的位用1表示.原因如下: 假设可以放牧的位用1表示,不可以放牧的位用0表示,那么假设当前行状态时1010   想要放置1001 ,&运算的结果是1,但是显然不合法, 也就是说  设值状态的意义,以及怎么判断是不是合法,这个在做之前一定考虑清楚再

poj3254(状压dp)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19518   Accepted: 10243 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 yu

POJ3254 状压dp

          Corn Fields Time Limit: 2000MS   Memory Limit: 65536K       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

poj 3254 Corn Fields 状压dp入门

// poj3254 状压dp入门 // dp[i][S]表示前i行第i行状态为S时放牧的情况 // S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数 // 首先dp[0][S]合法的话就是1 // 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态) // 最后的结果就是dp[n][S](S为所有的合法状态) // // 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数 // 这又不是求放羊的数量,这是方

第一次接触状压DP

状压DP入门及理解 *(另类的暴力)*      一般状态数不多的时候就会开数组,但是有的状态并不好表示,于是,状压DP就产生了.     状压DP应该是分两类的,一类是压缩状态,另一类是舍弃状态.    我感觉初学状压DP难就难在二进制运算的应用,了解二进制运算符就显得十分重要.     所以我们先看下表,如果有不会二进制简单应用的请点击https://blog.csdn.net/sinat_35121480/article/details/53510793(神犇请忽略...) 下面就可以看题

HDU 5823 (状压dp)

Problem color II 题目大意 定义一个无向图的价值为给每个节点染色使得每条边连接的两个节点颜色不同的最少颜色数. 对于给定的一张由n个点组成的无向图,求该图的2^n-1张非空子图的价值. n <= 18 解题分析 官方题解: 直接状压dp就行了,f[S]表示点集S的色数,枚举子集转移(子集是独立集).这样是3^n的. 一个复杂度更优的做法是把所有独立集都预处理出来,然后作n次or卷积.这样是n^2*2^n的. 枚举子集的子集的时间复杂度是3^n 啊 . 即 sigma( C(n,k

bzoj 1879: [Sdoi2009]Bill的挑战【状压dp】

石乐志写容斥--其实状压dp就行 设f[i][s]表示前i个字母,匹配状态为s,预处理g[i][j]为第i个字母是j的1~n的集合,转移的时候枚举26个字母转移,最后答案加上正好有k个的方案即可 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int mod=1000003; int T,n,m,len,t,f[55][50005],g[55][27],an

[BZOJ1087][SCOI2005]互不侵犯King解题报告|状压DP

在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 好像若干月前非常Naive地去写过DFS... 然后其实作为状压DP是一道非常好的题啦>< 感觉直接无脑搞时间是下不来的 做了好几道预处理 使得最后DP的过程中没有任何一条转移是无用的 1 program bzoj1087; 2 var i,x,n,k,j,p,q,t1,t2:longint; 3 ans:int64; 4 a:array[-1

poj3254 Corn Fields (状压DP)

http://poj.org/problem?id=3254 Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7588   Accepted: 4050 Description Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parc