状态压缩DP 第一题

题目链接

题意:一块 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值