【HDU1693】Eat the Trees(插头dp)

【HDU1693】Eat the Trees(插头dp)

题面

HDU
Vjudge
大概就是网格图上有些点不能走,现在要找到若干条不相交的哈密顿回路使得所有格子都恰好被走过一遍。

题解

这题的弱化版本吧。。。
因为可以任意分配哈密顿回路的数量,因此根本不需要再考虑插头的配对问题了,那么直接分情况转移就好啦。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 13
inline int read()
{
	int x=0;bool t=false;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
	if(ch=='-')t=true,ch=getchar();
	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
	return t?-x:x;
}
int bin[MAX];
ll f[MAX][MAX][1<<12];
int n,m;
int g[MAX][MAX];
int main()
{
	int T=read();
	bin[0]=1;for(int i=1;i<13;++i)bin[i]=bin[i-1]<<1;
	for(int TT=1;TT<=T;++TT)
	{
		n=read();m=read();memset(g,0,sizeof(g));memset(f,0,sizeof(f));
		for(int i=1;i<=n;++i)
			for(int j=1;j<=m;++j)
				g[i][j]=read();
		f[0][m][0]=1;int S=1<<(m+1);
		for(int i=1;i<=n;++i)
		{
			for(int k=0;k<S>>1;++k)f[i][0][k<<1]=f[i-1][m][k];
			for(int j=1;j<=m;++j)
				for(int k=0;k<S;++k)
				{
					int left=(k>>(j-1))&1,up=(k>>j)&1;
					if(!g[i][j])
					{
						if(!left&&!up)f[i][j][k]+=f[i][j-1][k];
						continue;
					}
					if(!left&&!up)
						if(g[i+1][j]&&g[i][j+1])f[i][j][k+bin[j-1]+bin[j]]+=f[i][j-1][k];
					if(!left&&up)
					{
						if(g[i+1][j])f[i][j][k+bin[j-1]-bin[j]]+=f[i][j-1][k];
						if(g[i][j+1])f[i][j][k]+=f[i][j-1][k];
					}
					if(left&&!up)
					{
						if(g[i+1][j])f[i][j][k]+=f[i][j-1][k];
						if(g[i][j+1])f[i][j][k-bin[j-1]+bin[j]]+=f[i][j-1][k];
					}
					if(left&&up)f[i][j][k-bin[j-1]-bin[j]]+=f[i][j-1][k];
				}
		}
		printf("Case %d: There are %lld ways to eat the trees.\n",TT,f[n][m][0]);
	}
}
posted @ 2018-12-09 17:56  小蒟蒻yyb  阅读(361)  评论(0编辑  收藏  举报