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

 
 
题意:给一个地图,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;
}
 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/xuyanqd/p/9051604.html