【插头dp】HDU1693 Eat the Trees

本文深入探讨了一种用于处理轮廓线插头的算法,通过分析不同情况下的插头配置,详细介绍了如何根据上下左右的位置状态调整插头,并提供了一个具体的代码实现案例,包括状态转移和边界条件的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

同样是轮廓线

我们有一下 种情况

1.这个位置左侧有插头,且右侧不是障碍

将其修改为

2.这个位置上面有插头,且下侧不是障碍

将其修改为

3.这个位置上、左都有插头,且当前节点不是障碍

将其修改为

4.如果这个位置上、左都没有插头

将其修改为

5.如果这个位置有障碍

当上和左都是0的时候,将其直接转移即可

 

 

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=13;
int t;
int n,m,ma[maxn][maxn];
long long f[maxn][maxn][1<<14];
int getbit(int s,int x)
{
	return (s>>x-1)&1;
}
int changebit(int s,int pos,int x)
{
	if(getbit(s,pos)!=x)
		return s^(1<<pos-1);
	return s;
}
int main()
{	
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);	
	scanf("%d",&t);
	for(int z=1;z<=t;z++)
	{
		scanf("%d%d",&n,&m);
		memset(ma,0,sizeof(ma));
		memset(f,0,sizeof(f));
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				scanf("%d",&ma[i][j]);
		f[1][1][0]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				for(int s=0;s<(1<<m+1);s++)
				{
					int up=getbit(s,j+1);
					int left=getbit(s,j);
					if(!f[i][j][s]) continue;
					//printf("f[%d][%d][%d]=%lld\n",i,j,s,f[i][j][s]);
					if(!ma[i][j])
					{
						if(!up && !left)
							f[i][j+1][s]=f[i][j][s];
						continue;
					}
					if(up && left)
					{
						int k=changebit(s,j+1,0);
						k=changebit(k,j,0);
						f[i][j+1][k]+=f[i][j][s];
						continue;
					}
					if(up || left)
					{
						int k=changebit(s,j+1,0);
						k=changebit(k,j,0);
						if(ma[i][j+1])
						{
							int t=changebit(k,j+1,1);
							f[i][j+1][t]+=f[i][j][s];
						}
						if(ma[i+1][j])
						{
							int t=changebit(k,j,1);
							f[i][j+1][t]+=f[i][j][s];
						}
						continue;
					}
					if(ma[i][j+1] && ma[i+1][j])
					{
						int t=changebit(s,j+1,1);
						t=changebit(t,j,1);
						f[i][j+1][t]+=f[i][j][s];
					}
				}
			}
			for(int s=0;s<(1<<m+1);s++)
				if(f[i][m+1][s]) f[i+1][1][s<<1]+=f[i][m+1][s];
		}
		printf("Case %d: There are %lld ways to eat the trees.\n",z,f[n+1][1][0]);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值