hdu1693:eat trees(插头dp)

时间:2023-03-09 08:39:15
hdu1693:eat trees(插头dp)

题目大意:

题目背景竟然是dota!屠夫打到大后期就没用了,,只能去吃树!

给一个n*m的地图,有些格子是不可到达的,要把所有可到达的格子的树都吃完,并且要走回路,求方案数

题解:

这题大概是最简单的插头dp了。。

比陈丹琦论文里的例题还要简单,因为允许有多个回路,所以不需要存储插头之间的连通性,直接二进制状压

搞清楚插头和轮廓线的概念基本就可以做出来了

这里有一些资料http://www.docin.com/p-741918386.html

代码:

#include <iostream>
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<string>
#include<ctype.h>
using namespace std;
#define MAXN 10000
long long dp[][][<<];
int g[][];
int n,m;
int main()
{
int t,cas=;
scanf("%d",&t);
while(t--)
{
cas++;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
for(int j=;j<=m;j++)
{
scanf("%d",g[i]+j);
}
}
memset(dp,,sizeof(dp));
dp[][m][]=;
for(int i=;i<=n;i++)
{
for(int j=;j<(<<m);j++)
{
dp[i][][j<<]=dp[i-][m][j];
}
for(int j=;j<=m;j++)
{
for(int k=;k<(<<(m+));k++)
{
int u=<<j;
int l=<<(j-);
if(g[i][j]==)
{
if((!(k&u))&&(!(k&l)))
dp[i][j][k]=dp[i][j-][k];
continue;
}
if((k&u)&&(k&l))
{
dp[i][j][k-u-l]+=dp[i][j-][k];
}
if((k&u)&&(!(k&l)))
{
dp[i][j][k]+=dp[i][j-][k];
dp[i][j][k-u+l]+=dp[i][j-][k];
}
if((k&l)&&(!(k&u)))
{
dp[i][j][k]+=dp[i][j-][k];
dp[i][j][k-l+u]+=dp[i][j-][k];
}
if((!(k&u))&&(!(k&l)))
{
dp[i][j][k+u+l]+=dp[i][j-][k];
}
}
}
}
printf("Case %d: There are %I64d ways to eat the trees.\n",cas,dp[n][m][]);
}
return ;
}