Corn Fields——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 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.ios

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)markdown

Output

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

Sample Input

2 3
1 1 1
0 1 0ui

Sample Output

9spa

Hint

Number the squares as follows:code

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.three

Source

USACO 2006 November Goldcoffeescript

題意:在一個n*m的草場上,每一塊草場均可以放一隻牛,有的草場是貧瘠的,因此不能放牛。因爲這些牛比較孤僻,因此不喜歡在本身吃草的地方周圍有其餘的牛(上下左右),問總共有多少种放法。ip

思路:在圖上的每個點均可能放牛(除去荒地),因此搜索的時間複雜度很高。

  • 假設咱們知道矩陣的n和m,咱們用二進制表示在一行的放牛的狀態(不考慮荒地),則全部的狀態爲[0,1 << m),狀態是否符合能夠根據(x&(x<<1)),返回值爲0表示沒有相鄰的1,則符合條件,不然不符合條件,這樣咱們就記錄在草場寬爲m時的全部能夠放的狀況,記錄在Sta數組中。
  • 因爲有荒地,因此對於每一行的第j個草地若是爲荒地則爲1,不然爲零,這樣就能夠每一行有一個數表示他們的草地的狀態,存在Map數組中,若是要判斷在符合狀況的方式中是否是有矛盾的,能夠用Map[i]&Sta[j]==0(表示第i行草地與第j種方式),若是等於零則符合,不等於零則不符合(在紙上寫寫看看爲何)。
  • 首先將第一行的因此狀態初始化即Dp[1][j]=(Map[1]&Sta[j])==0?1:0,而後根據第一行的全部狀態去枚舉第二行看是否符合,即
for i=2 -> n 
{
    for j=0 -> num
    {
        if Map[i]&Sta[j] == 1 
        {
            continue;
        }
        for k=0 -> num
        {
            if Map[i-1]&Sta[k] == 1
            {
                continue;
            }
            if Sta[j]&Sta[k]==0
            {
                Dp[i][j]+=Dp[i-1][k]
            }
        }
    }
}

具體狀況見代碼

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int Max = 1<<13;

const int Mod = 100000000; 

int Dp[15][Max];

int Map[15];

int Sta[Max];

bool Judge(int x)
{
    return (x&(x<<1));
}

bool Dec(int x,int y)
{
    return (Map[x]&Sta[y]);
}

int main()
{

    int n,m;

    while(~scanf("%d %d",&n,&m))
    {
        memset(Map,0,sizeof(Map));

        memset(Dp,0,sizeof(Dp));

        memset(Sta,0,sizeof(Sta));

        int data;

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&data);

                if(data==0)
                {
                    Map[i]+=(1<<(j-1)); //每一行的狀況用一個數來表示
                }
            }
        }

        int num = 0 ;

        for(int i=0;i<(1<<m);i++)//全部符合方式
        {
            if(!Judge(i))
            {
                Sta[num++] = i;
            }
        }

        for(int i=0;i<num;i++)//第一行的全部狀態初始化
        {
            if(!Dec(1,i))
            {
                Dp[1][i]=1;
            }
        }

        for(int i=2;i<=n;i++)
        {
            for(int j=0;j<num;j++)
            {
                if(Dec(i,j))// 是否符合
                {
                    continue;
                }

                for(int k=0;k<num;k++)
                {
                    if(Dec(i-1,k))//i-1行是否符合第k種狀況
                    {
                        continue;
                    }
                    if(!(Sta[j]&Sta[k])) //上下行之間也互相的知足條件
                    {
                        Dp[i][j]+=Dp[i-1][k];
                    }
                }
            }
        }

        int ans =0;

        for(int i=0;i<num;i++)
        {
            ans+=Dp[n][i];

            ans%=Mod;
        }

        printf("%d\n",ans);
    }
    return 0;
}
相關文章
相關標籤/搜索