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
Case 1: There are 3 ways to eat the trees. Case 2: There are 2 ways to eat the trees.
插头dp入门题。
最简单的插头dp题(其实本题的思路是简化的插头dp思路,并不广泛适用于插头dp的题目)
题解在这里
行与行之间的转移就是______|转移到|______,横线都是一样的,那么直接把上一行的左移一位就是这一行的第一个了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m,a[20][20];
long long f[20][20][1<<15];
void Plugdp()
{
f[0][m][0]=1;
for (int i=1;i<=n;i++)
{
for (int j=0;j<(1<<m);j++)
f[i][0][j<<1]=f[i-1][m][j];
for (int j=1;j<=m;j++)
for (int k=0;k<(1<<(m+1));k++)
{
int y=1<<j,x=1<<(j-1);
if (a[i][j])
{
if ((k&y)&&(k&x))
f[i][j][k]=f[i][j-1][k-x-y];
else if (!(k&x)&&!(k&y))
f[i][j][k]=f[i][j-1][k+x+y];
else f[i][j][k]=f[i][j-1][k^x^y]+f[i][j-1][k];
}
else
{
if (!(k&x)&&!(k&y))
f[i][j][k]=f[i][j-1][k];
else f[i][j][k]=0;
}
}
}
printf("There are %lld ways to eat the trees.\n",f[n][m][0]);
}
int main()
{
int T;
scanf("%d",&T);
for (int i=1;i<=T;i++)
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
printf("Case %d: ",i);
Plugdp();
}
return 0;
}
原文:http://blog.csdn.net/regina8023/article/details/44836669