其他分享
首页 > 其他分享> > P5074 Eat the Trees

P5074 Eat the Trees

作者:互联网

Eat the Trees

Luogu P5074

题目背景

HDU1693:Eat the Trees

题目描述

给出n*m的方格,有些格子不能铺线,其它格子必须铺,可以形成多个闭合回路。问有多少种铺法?

输入格式

每个测试点多组数据

第一行一个正整数T,表示有T组数据

每组数据:

第1行,n,m(2<=n,m<=12)

从第2行到第n+1行,每行m个数字(1 or 0),1表铺线,0表不铺线

输出格式

每组数据输出一个整数(表方案数)

样例 #1

样例输入 #1

2
6 3
1 1 1
1 0 1
1 1 1
1 1 1
1 0 1
1 1 1
2 4
1 1 1 1
1 1 1 1

样例输出 #1

3
2

Solution

算是个插头 DP 的基础题了,甚至比洛谷上插头 DP 的模板题还要简单。

假设一个 DP 数组 \(f[i][j][s]\) 表示当前枚举到了 \((i,j)\) 的格子,并且当前轮廓线的状态为 \(s\),那么按照插头 DP 模板的思路,先获取当前格子左侧插头 \(isR=s>>(j-1)\) 和上侧插头 \(isD=s>>j\),进行分类讨论:

到达每一行的第一个的时候需要将轮廓线给滚到下一行,具体做法就是 \(f[i][0][j<<1]=f[i-1][m][j]\),这样就可以做到把插头全部右移一位了。

Code

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
#define bit(a,b) (a>>b-1&1) //表示a二进制上第b位的数字
using namespace std;
template<typename T> void read(T &k)
{
	k=0;T flag=1;char b=getchar();
	while (!isdigit(b)) {flag=(b=='-')?-1:1;b=getchar();}
	while (isdigit(b)) {k=k*10+b-48;b=getchar();}
	k*=flag;
}
bool mp[15][15];
int n,m,T,maxn;
const int _SIZE=1<<14;
long long f[15][15][_SIZE+5];
int main()
{
	read(T);
	while (T--)
	{
		read(n),read(m);
		maxn=1<<(m+1);mem(f,0);
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++) read(mp[i][j]);
		mem(f,0);
		f[0][m][0]=1;
		for (int i=1;i<=n;i++)
		{
			for (int j=0;j<maxn;j++) f[i][0][j<<1]=f[i-1][m][j];
			for (int j=1;j<=m;j++)
			{
				for (int k=0;k<maxn;k++)
				{
					int isR=bit(k,j),isD=bit(k,j+1),nowsta=k;
					long long nowans=f[i][j-1][k];
					if (!mp[i][j]) 
					{
						if ((!isD) && (!isR)) f[i][j][nowsta]+=nowans;
					}
					else if ((!isD) && (!isR))
						f[i][j][nowsta+(1<<j-1)+(1<<j)]+=nowans;
					else if ((!isR) && isD)
					{
						if (mp[i][j+1]) f[i][j][nowsta]+=nowans;
						if (mp[i+1][j]) f[i][j][nowsta-(1<<j)+(1<<j-1)]+=nowans;
					}
					else if (isR && (!isD))
					{
						if (mp[i+1][j]) f[i][j][nowsta]+=nowans;
						if (mp[i][j+1]) f[i][j][nowsta-(1<<j-1)+(1<<j)]+=nowans;
					}
					else 
						f[i][j][nowsta-(1<<j-1)-(1<<j)]+=nowans;
				}
			}
		}
		printf("%lld\n",f[n][m][0]);
	}
	return 0;
}

标签:插头,格子,isR,Trees,P5074,Eat,DP,isD
来源: https://www.cnblogs.com/hanx16msgr/p/16576322.html