Corn Fields
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 6106   Accepted: 3235

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的土地来种地,有地地方不能种,每一块有corn的地不能有临边,问方案由多少种


一看n和m那么小的范围就知道是状压dp……好久没碰状压了有点心虚…………
所谓的状态压缩就是用二进制(或者三进制四进制等等)来表示状态,通过位运算的方式判断是否可以转移
首先要通过枚举得出所有在单行可行的状态,即没有两个相邻的1——判断方法是(i &(i >>1 )== 0)
然后转移方程是这样的:
如果第k个状态在第i行可行(a[i] & state[k]),且与前一行状态为第j个不冲突(state[k] & state[j]) == 0)
f[k][i]  +=  f [j] [i - 1];

提醒注意边界啊,我是习惯把第一行先单独处理出来做边界!
ps:可以用01滚动……

做这个题的时候出了各种各样的问题,比如最开始没看到方案数要取模,更脑残的是单独处理第一行的时候没有判断是否可行(地面有的地方不能种啊orz  )还有滚动数组滚动过程中没有清零……然后就因为这些各种残的问题华丽丽的wa了5次……吸取教训啊啊啊

#include <iostream>
#include <cstring>
#include <cstdio>
const long N = 14, SUM = 4100;

long n, m, t;
long a[N];
long f[SUM][2];
long state[SUM];
using namespace std;
int main()
{
    freopen("poj3254.in", "r", stdin);
    memset(state, 0 , sizeof(state));
    while (scanf("%d%d", &n, &m) != EOF)
    {
        long tmp;
        for (long i = 1; i <= n; i++)
        {
            a[i] = 0;
            for (long j = 1; j <= m; j++)
            {
                scanf("%d", &tmp);
                if (tmp != 1)
                {
                    a[i] = a[i] + (1 << (j - 1));
                }
            }
        }
        t = 0 ;
        long r = (1 << m) - 1;
        for (long i = 0; i <= r; i++)
        {
            if ((i & (i >> 1)) == 0)
                state[++t] = i;
        }
        
        memset(f, 0, sizeof(0));
        for (long i = 1; i <= t; i++)
        {
            if ((a[1] & state[i]) == 0) f[i][0] =  1;
        }


        long p = 0;
        long q = 1;
        for (long i = 2; i <= n; i++)
        {
            for (long j = 1; j <= t; j++)
                f[j][q] = 0;
            for (long j = 1; j <= t; j++)
            for (long k = 1; k <= t; k++)
            {
                if (((state[k] & state[j]) == 0)&&((a[i] & state[k]) == 0))
                {

                    f[k][q] = (f[k][q] + f[j][p])% 100000000;
                   // cout << state[k]<<' '<<state[j] <<' '<< f[k][q] << endl;
                }
            }
            p = p ^ 1;
            q = q ^ 1;
        //cout << endl;
        }
        long re = 0;
        for (long i = 1; i <= t; i++)
        {
            re = (re + f[i][p]) % 100000000;
        }
        cout << re <<endl;



    }
    return 0;
}