poj 2441 Arrange the Bulls 状压dp入门

题意:

将n头牛和m个栏做匹配,求匹配方案数。

分析:

开始暴搜tle了,还是要用状压dp,dp[i][s]表示前i头牛匹配栏的状态为s时可行的方案数。

代码:

//poj 2441
//sep9
#include <iostream>
using namespace std;
const int maxN=21;
int dp[2][1<<maxN];
int a[maxN][maxN];
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i][0]);
		for(int j=1;j<=a[i][0];++j){
			scanf("%d",&a[i][j]);
			--a[i][j];
		}
	}
	memset(dp,0,sizeof(dp));
	for(int i=1;i<=a[1][0];++i)
		dp[1][1<<a[1][i]]=1;
	int x=0,y=1;
	for(int i=2;i<=n;++i){
		x=y;
		y=x^1;
		memset(dp[y],0,sizeof(dp[y]));
		for(int s=0;s<(1<<m);++s){
			if(dp[x][s])
				for(int j=1;j<=a[i][0];++j){
					int k=(1<<a[i][j]);
					if((s&k)==0)
						dp[y][s|k]+=dp[x][s];
				}
		}
	}
	int ans=0;
	for(int i=0;i<(1<<m);++i)
		ans+=dp[y][i];
	printf("%d",ans);
}
时间: 2024-11-10 08:12:24

poj 2441 Arrange the Bulls 状压dp入门的相关文章

poj 2411 Mondriaan&#39;s Dream 状压dp入门

题意: 求h*w的矩形被1*2的小矩形覆盖的方案数. 分析: 状压dp入门,<挑战程序设计竞赛>上讲的很好,好几天才看懂. 代码: #include <iostream> using namespace std; __int64 ans[16][16]; int n,m; __int64 dp[2][1<<16]; __int64 solve() { int i,j,used; memset(dp,0,sizeof(dp)); __int64 *crt=dp[0],*n

POJ 1185 炮兵阵地(状压DP入门)

http://poj.org/problem?id=1185 状压DP: 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 int dp[105][100][100]; 7 int ma[105],st[105]; 8 9 int ok(int x) 10 { 11 return (x&(x<<1))+(x&(x&

POJ 2441 Arrange the Bulls(状态压缩DP)

Arrange the Bulls Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 4234   Accepted: 1612 Description Farmer Johnson's Bulls love playing basketball very much. But none of them would like to play basketball with the other bulls because the

poj 2441 Arrange the Bulls (状态压缩dp+滚动数组)

题意: n头牛和m个barn,每头牛有自己喜欢的p个barn(1<=p<=m),问有多少种安排n头牛的方法. 分析: dp[i][j]表示i头牛在j状态下的方法数. dp[i][j] = sigma(dp[i-1][k])  (k从0到 1<<m). 要用滚动数组优化,否则dp[20][1<<20]会MLE! 注意滚动数组的清空= =! 1 #include<stdio.h> 2 #include<cstring> 3 #include<i

POJ 2411 Mondriaan&#39;s Dream(状压DP)

http://poj.org/problem?id=2411 求一个n*m矩阵用1*2方块去填满的情况有几种 思路:状压dp,先预处理那些状态之间能互相到达,情况就几种,上一个两个1,下一个状态也两个1,上一个为0,下一个必须为1,还有一种是上一个为1,下一个为0的情况 然后就一层层往后递推即可 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int

POJ 2411 Mondriaan&#39;s Dream ——状压DP 插头DP

[题目分析] 用1*2的牌铺满n*m的格子. 刚开始用到动规想写一个n*m*2^m,写了半天才知道会有重复的情况. So Sad. 然后想到数据范围这么小,爆搜好了.于是把每一种状态对应的转移都搜了出来. 加了点优(gou)化(pi),然后poj上1244ms垫底. 大概的方法就是考虑每一层横着放的情况,剩下的必须竖起来的情况到下一层取反即可. 然后看了 <插头DP-从入门到跳楼> 这篇博客,怒抄插头DP 然后16ms了,自己慢慢YY了一下,写出了风(gou)流(pi)倜(bu)傥(tong)

POJ 2411 Mondriaan&#39;s Dream (状压DP)

题意:给出一个n*m的棋盘,及一个小的矩形1*2,问用这个小的矩形将这个大的棋盘覆盖有多少种方法. 析:对第(i,j)位置,要么不放,要么竖着放,要么横着放,如果竖着放,我们记第 (i,j)位置为0,(i+1,j)为1,如果横着放,那么我们记 (i,j),(i,j+1)都为1,然后dp[i][s]表示 第 i 行状态为 s 时,有多少方法,那么我们就可以考虑与和匹配的状态,这个也很容易判断. 代码如下: #pragma comment(linker, "/STACK:1024000000,102

POJ 3254 Corn Fields 【状压DP】

[题目大意]一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻.问有多少种放牛方案(一头牛都不放也是一种方案) [解析]根据题意,把每一行的状态用二进制的数表示,0代表不在这块放牛,1表示在这一块放牛.首先很容易看到,每一行的状态要符合牧场的硬件条件,即牛必须放在能放牧的方格上.这样就能排除一些状态.另外,牛与牛之间不能相邻,这样就要求每一行中不能存在两个相邻的1,这样也能排除很多状态.

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的个数 // 这又不是求放羊的数量,这是方