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