【插头DP】广场铺砖

广场铺砖问题(floor.pas/c/cpp)
 
有一个 W 行 H 列的广场,需要用 1*2小砖铺盖,小砖之间互相不能重叠,问
有多少种不同的铺法?
 
输入数据:
只有一行 2个整数,分别为 W 和 H,(1<=W,H<=11)
 
输出数据:
  只有 1个整数,为所有的铺法数。
 
样例:
  Floor.in
  2 4
  Floor.out
  5
 
样例铺法如下图:
 


感觉是SCOI2011的简化版,因为只用记录有没有插头。

这道题的范围比较小。

总方案数是2^12。.

如果用开散列会超时

如果不用散列表也会超时

所以就用普通的散列表就不会超时了。。。。。。。

注意必须用long long否则大数据要爆。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using std::swap;

long w;long h;
long ths = 1;
long pre = 0;
const long MaxStaus = 4100;
long cnt[2];
long long f[2][MaxStaus];
long Status[2][MaxStaus];
long tmp[MaxStaus];


long get_ID(long Sta)
{
	if (tmp[Sta]>0)
		return tmp[Sta];
	cnt[ths] ++;
	f[ths][cnt[ths]] = 0;
	tmp[Sta] = cnt[ths];
	Status[ths][cnt[ths]] = Sta;
	return cnt[ths];
}

void clear()
{
	cnt[ths] = 0;
	memset(tmp,0,sizeof(tmp));
}

void dp()
{
	f[ths][get_ID(0)] = 1;
	for (long i=1;i<w+1;i++)
	{
		for (long j=1;j<h+1;j++)
		{
			swap(ths,pre);
			clear();
			for (long k=1;k<cnt[pre]+1;k++)
			{
				long Last = Status[pre][k];
				long long val = f[pre][k];
				if (j == 1)
				{
					if ((Last&1) == 0)
					{
						Last >>= 1;
					}
					else continue;
				}
				long q = h-j;
				long p = q+1;
				long wp = (Last>>p)&1;
				long wq = (Last>>q)&1;
				long Now = Last - (wq<<q) - (wp<<p);
				
				if (wp == 1 && wq == 1)
					continue;
				if (wp == 0 && wq == 0)
				{
					f[ths][get_ID(Now|(1<<q))] += val;
					f[ths][get_ID(Now|(1<<p))] += val;
				}
				if (wp == 0 && wq == 1)
				{
					f[ths][get_ID(Now)] += val;
				}
				if (wp == 1 && wq == 0)
				{
					f[ths][get_ID(Now)] += val;
				}
			}
		}
	}
	std::cout << f[ths][get_ID(0)];
}

int main()
{
	freopen("floor.in","r",stdin);
	freopen("floor.out","w",stdout);
	std::cin >> w >> h;
	dp();
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值