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
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
Sample Input
2 3 1 1 1 0 1 0
Sample Output
9
Hint
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.
先说几句题外话:很感谢他(一大牛), 以一道题为例给我讲了一晚上,虽然那道题我还是没太明白,但是明显感觉我现在对于状态压缩开窍了,能看懂了,很感谢他...ORZ
引用他给我讲的:就是有一些问题有很多状态,而这些状态的描述以及状态之间的关系能够用一个整形数简单的表示的话 ,那么就可以考虑用状压dp;
状态压缩也是对空间可时间的一种优化;
题目大意:0表示不能放牛,1表示可以放牛,但是牛与牛之间是不能挨着,共有多少种放置牛的方法;
解题思路:将一行的状态表示为1 0 1二进制数字,即可化为一个整数代替;假设上一行(i-1行)状态为1 0 1(1表示放置牛) 那么他的下一行的合法状态有 0 0 0; 0 1 0;那么 对于第i行的状态至于上一行有关系即状态转移方程如下:dp[i][j]表示第i行状态为j时的数目;
dp[i][j]=sum(dp[i-1][k]){k!=j, &&k属于对于i行的合法状态}
代码如下:
#include<stdio.h> #include<string.h> #include<iostream> #include<math.h> using namespace std; #define N 13 #define M 1<<N #define mod 100000000 int state[M], map[N], dp[N][M]; int judge1(int x) { if(x&(x<<1)) return 0; return 1; } int judge2(int i, int k) { if(map[i]&state[k]) return 0; return 1; } int main() { int i, j, m, n, a, tt, k, oknum; while(scanf("%d%d", &n, &m)!=EOF) { memset(map, 0, sizeof(map)); memset(state, 0, sizeof(state)); memset(dp, 0, sizeof(dp)); for(i=1; i<=n; i++) { for(j=1; j<=m; j++) { scanf("%d", &a); if(a==0) map[i]+=1<<(m-j); } } tt=(1<<m)-1; oknum=0; for(i=0; i<=tt; i++) { if(judge1(i)) state[oknum++]=i; } for(i=0; i<oknum; i++) { if(judge2(1, i)) dp[1][i]=1; } for(i=2; i<=n; i++) { for(j=0; j<oknum; j++) { if(!judge2(i, j)) continue; for(k=0; k<oknum; k++) { if(!judge2(i-1, k)) continue; if(!(state[j]&state[k])) dp[i][j]=(dp[i][j]+dp[i-1][k])%mod; } } } int ans=0; for(i=0; i<oknum; i++) ans=(ans+dp[n][i])%mod; printf("%d\n", ans); } }