1. 程式人生 > >poj3254 狀壓dp 每行獨立 入門水題

poj3254 狀壓dp 每行獨立 入門水題

cows angular 不可 可用 href IT usaco scanf clas

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;
}

poj3254 狀壓dp 每行獨立 入門水題