HDU 1693 Eat the Trees(插头DP)

时间:2023-12-20 19:39:08

题目链接

USACO 第6章,第一题是一个插头DP,无奈啊。从头看起,看了好久的陈丹琦的论文,表示木看懂。。。

大体知道思路之后,还是无法实现代码。。

此题是插头DP最最简单的一个,在一个n*m的棋盘上,有些点能走,有些点不能走,可以走一条回路,也可以多回路,把所有点走完,有多少种走法。。

这题的背景还是dota,还是屠夫,还是吃树。。。我还是不会玩屠夫啊。。。

学习此题,看的下面的大神的博客,图画很棒,位运算又学了一个新用法。

http://blog.csdn.net/xymscau/article/details/6756351

 #include <cstdio>
#include <cstring>
using namespace std;
#define LL __int64
LL dp[][][<<];
int p[][];
int main()
{
int i,j,k,n,m,t,te1,te2,cas = ;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
memset(dp,,sizeof(dp));
for(i = ;i <= n;i ++)
{
for(j = ;j <= m;j ++)
{
scanf("%d",&p[i][j]);
}
}
dp[][m][] = ;
for(i = ;i <= n;i ++)
{
for(j = ;j < <<m;j ++)//换行
dp[i][][j<<] = dp[i-][m][j];
for(j = ;j <= m;j ++)
{
te1 = <<j;
te2 = <<(j-);
for(k = ;k < <<(m+);k ++)
{
if(p[i][j])//此位置可以走
{
if((k&te1)&&(k&te2))//这个格子有两个插头
dp[i][j][k] = dp[i][j-][k-te1-te2];
else if((k&te1) == &&(k&te2) == )//都没有插头
dp[i][j][k] = dp[i][j-][k|te1|te2];
else
dp[i][j][k] = dp[i][j-][k] + dp[i][j-][k^te1^te2];//k^te1^te2表示的在k位和k-1位,变成相反
}
else
{
if((k&te1) == &&(k&te2) == )
dp[i][j][k] = dp[i][j-][k];
else
dp[i][j][k] = ;
}
}
}
}
printf("Case %d: There are %I64d ways to eat the trees.\n",cas++,dp[n][m][]);
}
return ;
}