poj-3254 Corn Fields(状态压缩dp)

Corn Fields

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 20342   Accepted: 10679

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.

//题目大意:有一片n*m的农场,1表示有草,0表示没草,在每个有草的格子里放牛,要求每头牛互不相邻;

//思路:n和m范围不大,考虑状压dp,dp[i][j],i(i>=1&&i<=n)表示行,j (j>=0&&j<(1<<m))表示每行的状态;

先找出所有符合条件的状态,利用   i&(i<1)   可以判断有没有相邻的1;

然后,判断上下行有没有相邻的1,可以利用  j&k  来判断,如果上下行没有相邻的1,则f[i][j]= f[i][j]+f[i-1][k] ;

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAX=1<<12;
int f[13][MAX];
int a[13][13];//存图
int m,n;
const int mod=1e8;
int check(int row,int num)//判断该状态是否符合所给的图
{
    int flag=1;
    for(int i=0;i<n;i++)
    {
        if((num&(1<<i))!=0)
        {
            if(a[row][n-1-i]==1)flag=1;
            else {flag=0;break;}
        }
    }
    return flag;
}
int main()
{
    while(~scanf("%d%d",&m,&n))
    {
        memset(f,0,sizeof(f));
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
                scanf("%d",&a[i][j]);
        }
        for(int j=0;j<(1<<n);j++)
        {
            //cout<<j<<"&&&"<<(j&(j<<1))<<" "<<check(0,j)<<endl;
            if(!(j&(j<<1))&&check(0,j))f[0][j]=1;
            //cout<<"***"<<f[0][j]<<endl;
        }
        //cout<<check(1,4)<<"((((((((("<<endl;
        for(int i=1;i<m;i++)
        {
            for(int j=0;j<(1<<n);j++)
            {
                if(!(j&(j>>1))&&check(i,j))//每一行有x中状态
                {
                    //cout<<j<<":"<<endl;
                    for(int k=0;k<(1<<n);k++)//每一种状态与上一行的y中状态匹配
                    {
                        if(!(k&(k>>1))&&check(i-1,k))
                        {
                            //cout<<k<<endl;
                            if((j&k)==0)f[i][j]+=f[i-1][k];
                        }
                    }
                }
            }
        }
        ll ans=0;
        for(int i=0;i<(1<<n);i++)
        {
            ans=(ans+f[m-1][i])%mod;//把最后一行的每一种状态相加
        }
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37378303/article/details/82500656