poj 3254 Corn Fields 状压dp入门

// poj3254 状压dp入门
// dp[i][S]表示前i行第i行状态为S时放牧的情况
// S为十进制的二进制数形式如5为101表示第一列和第三列放牧的方法数
// 首先dp[0][S]合法的话就是1
// 状态转移方程为dp[i][S] = sigma(dp[i-1][V])(S与V是合法状态)
// 最后的结果就是dp[n][S](S为所有的合法状态)
//
// 刚开始十分傻x的dp[0][S]置为get(S),...get(S)是其中1的个数
// 这又不是求放羊的数量,这是方法数,完全对自己无语了。。。
// 不过,最后把get(S)改为1就ac啦~~~还是很开心的
// wa了无数发啊,哎。。。继续练吧。。。。
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfloat>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#define ceil(a,b) (((a)+(b)-1)/(b))
#define endl '\n'
#define gcd __gcd
#define highBit(x) (1ULL<<(63-__builtin_clzll(x)))
#define popCount __builtin_popcountll
typedef long long ll;
using namespace std;
const int MOD = 1000000007;
const long double PI = acos(-1.L);

template<class T> inline T lcm(const T& a, const T& b) { return a/gcd(a, b)*b; }
template<class T> inline T lowBit(const T& x) { return x&-x; }
template<class T> inline T maximize(T& a, const T& b) { return a=a<b?b:a; }
template<class T> inline T minimize(T& a, const T& b) { return a=a<b?a:b; }

const int maxn = 15;
int dp[maxn][1<<maxn];
int n,m;
int state[maxn];

const int M = 1e8;

bool ok(int x){
	if (x&(x<<1))	return false;
	return true;
}

int get(int x){
	int cnt = 0;
	while(x){
		if (x&1)
			cnt++;
		x>>=1;
	}
	return cnt;
}

void init(){
	int a;
	memset(state,0,sizeof(state));
	for (int i=0;i<n;i++){
		for (int j=0;j<m;j++){
			scanf("%d",&a);
			if (!a){
				state[i] = state[i] | (1<<j);
			}
		}
	}
	memset(dp,0,sizeof(dp));
	for (int i=0;i<(1<<m);i++){
		if (i&state[0])	continue;
		if (ok(i)){
			dp[0][i] = 1;
		}
	}
}

void print(){
	for (int i=0;i<n;i++){
		for (int j=0;j<(1<<m);j++)
			printf("%d ",dp[i][j]);
		puts("");
	}
}

void solve(){
	for (int i=1;i<n;i++){
		for (int S=0;S<(1<<m);S++){
			if (!ok(S))	continue;
			if (S&state[i]) continue;
			for (int V=0;V<(1<<m);V++){
				if (!ok(V))	continue;
				if (S&V)	continue;
				if (V&state[i-1])	continue;
				dp[i][S] = (dp[i][S]+dp[i-1][V])%M;
			}
		}
	}
//	print();
	int ans = 0;
	for (int i=0;i<(1<<m);i++)
		if (ok(i))
			ans =(ans+dp[n-1][i])%M;
	printf("%d\n",ans);
}

int main() {
    //freopen("G:\\Code\\1.txt","r",stdin);
	while(scanf("%d%d",&n,&m)!=EOF){
		init();
		solve();
	}
	return 0;
}

时间: 2024-10-13 01:48:30

poj 3254 Corn Fields 状压dp入门的相关文章

POJ 3254 Corn Fields 状压DP

链接:http://poj.org/problem?id=3254 题意:一块M*N的田地,每小块地大小是1*1,可以种植物的标记为1,不可以种植物的标记为0,并且相邻的两块地不可以同时种植物.问题是有多少种不同的种植方案(所有地都不种也是一种种植方案) 思路:这是第一道状压DP题,从第一行更新到最后一行,每一行用一个N位的二进制数来表示该行的状态1表示该位置种了植物,0表示该位置没种植物.因为每块地只对相邻的土地能否种植有所影响,所以每一行的状态可以用前一行的状态递推得到. 资料:http:/

[ An Ac a Day ^_^ ] POJ 3254 Corn Fields 状压dp

题意: 有一块n*m的土地 0代表不肥沃不可以放牛 1代表肥沃可以放牛 且相邻的草地不能同时放牛 问最多有多少种放牛的方法并对1e8取模 思路: 典型的状压dp 能状态压缩 能状态转移 能状态压缩的题的特点就是只有两种状态 所以用0 1表示两种状态 用位运算判断是否符合条件 然后将前一行的合理状态转移到后一行 最后统计最后一行的状态 dp[i][j]代表第i行以第j种状态放牛时有多少种不同的状态 (c++的语言特性是 封装 继承 多态~) 1 /* ***********************

POJ 3254 Corn Fields (状压DP+滚动数组)

题目地址:POJ 3254 状压水题. 先预处理出每行所有可能出现的情况.然后可以用vector存起来. 然后先处理出第一行所有的情况.然后再从第二行开始不断与上一行进行状态转移,状态转移很简单就不说了. 最后统计出最后一行的个数和就可以了. 代码如下; #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #

POJ 1684 Corn Fields(状压dp)

描述 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

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

题解——[USACO06NOV]玉米田Corn Fields 状压DP

题面: 农场主John新买了一块长方形的新牧场,这块牧场被划分成M行N列(1 ≤ M ≤ 12; 1 ≤ N ≤ 12),每一格都是一块正方形的土地.John打算在牧场上的某几格里种上美味的草,供他的奶牛们享用. 遗憾的是,有些土地相当贫瘠,不能用来种草.并且,奶牛们喜欢独占一块草地的感觉,于是John不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边. John想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择?(当然,把新牧场完全荒废也是一种方案) 输出一个整数,即牧

P1879 [USACO06NOV]玉米田Corn Fields 状压dp

链接在此! 正解:状压dp(emm……据说插头dp也可以趴但我不管!!!不会!!! 解题报告: ……我真的太菜了……我以为一个小时前要搞完的题目调错误调了一个小时……90分到100我差不多搞了一个小时…… 然后这题还是做过的……就很气,觉得确实是要搞下博客没事儿复习下不然做过的题目还花俩小时我真的哭死…… 先放上错误的90分代码讲一下错哪儿了(因为……其实100并不难是可以想到的……没有太大讲的意义,主要我太菜了所以才会搞这么久TT 点我♂看♂沙雕灵巧在线WA题 然后错误的点是最后一个点RE,开

[USACO06NOV]玉米田Corn Fields (状压$dp$)

题目链接 Solution 状压 \(dp\) . \(f[i][j][k]\) 代表前 \(i\) 列中 , 已经安置 \(j\) 块草皮,且最后一位状态为 \(k\) . 同时多记录一个每一列中的不能放的位置 \(w[i]\). 然后就可以很轻松的转移了... 转移方程看代码. Code #include<bits/stdc++.h> #define ll long long using namespace std; ll f[13][145][10000],n,K; ll js[1000

POJ 3254. Corn Fields 状态压缩DP (入门级)

Corn Fields Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 9806   Accepted: 5185 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 yumm