题意:一块 m * n 的土地 (1 ≤ m ≤ 12; 1 ≤ n ≤ 12),给出其每个方块的贫瘠情况,现要在其上栽种玉米,要求任何两块栽种玉米的地方不能有相邻的边,问玉米的栽种方法一共有几种(一块地都不栽种也属于方法的一种)?
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define INF 2048
#define nMAX 13
int state[nMAX]; //玉米栽种状况的状态压缩数组 s[i] = j 表示第i 个状态为j,
//其中j 的二进制表示中为1 的位置表示种玉米,为0 的则表示不种
int f[nMAX][INF]; //f[i][j] = x 表示到第i 行为止,第i 行能栽种s[j] 的情况有x 种
int map[nMAX]; //土地状况的状态压缩数组,map[i] = j 表示第i 行土地的状态用j 表示,
//其中j 的二进制表示中为1 的位置表示富饶(可用于种玉米), 为0 的则表示贫瘠(不可用于种玉米)
const int mod = 100000000; //题目要求最后的结果需模这个数
int main()
{
int i, j, k, m, n, a;
scanf("%d%d", &m, &n); // m * n 的土地
bool flag = false;
int size = 0, count;
输入土地贫瘠状况
for( i = 1; i <= m; i ++ ){
for( j = 1; j <= n; j ++ ){
scanf("%d", &a);
map[i] = ( map[i] << 1 ) + a;
}
}
计算每行允许栽种的情况数size
for( i = 0; i < ( 1 << n ); i ++ ){
int ii = i;
flag = false;
while( ii > 0 ){
if( ( ii & 1 ) == 1 ){
不允许相邻栽种
if( flag )
break;
else flag = true;
}
else flag = false;
ii = ii >> 1;
}
if( ii == 0 ){
if( ( map[1] | i ) == map[1] ) ///忘了这个条件,wa了几次
f[1][size] = 1;
state[size++] = i;
}
}
for( i = 2; i <= m; i ++ ) //第i 行
for( k = 0; k < size; k ++ )
if( f[i - 1][k] > 0 ){ //枚举第i - 1 行允许的状态 k
for( j = 0; j < size; j ++ ){ //循环所有的状态 j
if( ( state[k] & state[j] ) == 0 ){ //s[k] 和s[j] 没有同为1 的位(即玉米栽种没有上下相邻的情况)
if( ( map[i] | state[j] ) == map[i] ){ //s[j] 的栽种符合该行土地的贫瘠情况
f[i][j] += f[i - 1][k]; //如果上述情况都符合则状态数相加
f[i][j] %= mod;
}
}
}
}
int sum = 0;
for( i = 0; i < size; i ++ ){
sum += f[m][i];
sum %= mod;
}
printf("%d\n", sum );
return 0;
}