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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章