POJ 2441 Arrange the Bulls

题意:给你n头牛以及m个房间,每头牛只可放在一些固定的房间,求每头牛都放置到房间中的方案数。

思路:用dp[i][j]表示第i头牛在状态j时的方案数,则,dp[i][j] += dp[i-1][k];其中k为前i-1头牛放置成状态k的方案数,要保证在放第i头牛的位置为0。这样写空间消耗太大,

故需要改成滚动数组。dp[cnt][x] += dp[1-cnt][k];x为第i头牛可以放到房间的状态。

将第二层的循环作为状态,可以节约更多时间。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <map>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef __int64 int64;
typedef long long ll;
#define M 100005
#define max_inf 0x7f7f7f7f
#define min_inf 0x80808080
#define mod 1000000007

int n , m , dp[2][1<<20];
vector<int> cow[25];

int Solve()
{
	int i , j , k , up , cnt = 1;
	int size = 1<<m;
	memset(dp , 0 , sizeof dp);
	dp[0][0] = 1;
	for (i = 0 ; i < n ; i++)
	{
		memset(dp[cnt] , 0 , sizeof dp[cnt]);
		for (k = 0 ; k < size ; k++)
		{
			if (!dp[1-cnt][k])continue;
			int up = cow[i].size();
			for (j = 0 ; j < up ; j++)
			{
				int temp = cow[i][j];
				if (k&(1<<temp))continue;
				int x = k+(1<<temp);
				dp[cnt][x] += dp[1-cnt][k];
			}
		}
		cnt = 1-cnt;
	}
	cnt = 1-cnt;
	int ret = 0;
	for (i = 0 ; i < size ; i++)
		ret += dp[cnt][i];

	return ret;
}

int main()
{
	while (~scanf("%d%d",&n,&m))
	{
		int i;
		for (i = 0 ; i < n ; i++)cow[i].clear();
		for (i = 0 ; i < n ; i++)
		{
			int q , x;
			scanf("%d",&q);
			while (q--)scanf("%d",&x),cow[i].push_back(x-1);
		}
		if (m < n)
			printf("0\n");
		else
			printf("%d\n",Solve());
	}
	return 0;
}


 

发布了98 篇原创文章 · 获赞 1 · 访问量 4万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章