百度一下:基于连通性状态压缩的动态规划问题
#include <iostream>
using namespace std;
const int maxn = 12;
__int64 dp[maxn][maxn][1<<maxn];
int mp[12][12];
int main(){
int T;
scanf("%d",&T);
for(int Case=1;Case<=T;Case++){
int i,j,k,m,n;
scanf("%d%d",&m,&n);
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
memset(dp,0,sizeof(dp));
dp[0][n][0]=1;
for(i=1;i<=m;i++){
for(j=0;j<(1<<n);j++)
dp[i][0][j<<1]=dp[i-1][n][j];
//把状态下拉一行
//[i,n]的状态x和[i+1,0]的状态x是对应相同的
//所以也避免了初始化的麻烦
//上一行最右边的边格一定不与轮廓线重合
//下一行最左边的边格一定不与轮廓线重合
for(j=1;j<=n;j++){
for(k=0;k<(1<<(n+1));k++){
int p = 1<<j;
//(i,j)轮廓段上插头
int q = p>>1;
//(i,j)轮廓段左插头
bool x = p & k;
bool y = q & k;
if (mp[i][j]){//可以走
dp[i][j][k]=dp[i][j-1][k^p^q];
//必然有一个通路连接上一个格子的通路
if (x!=y)
dp[i][j][k]+=dp[i][j-1][k];
//有一处新覆盖则有另外的一种情况
}
else{//为障碍格子
if (x+y==0)//道路与轮廓线不相交
dp[i][j][k]=dp[i][j-1][k];//和前面一个格子的状态数相同
else
dp[i][j][k]=0;
//不合法,障碍格子不可能与轮廓线相交
}
}
}
}
printf("Case %d: There are %I64d ways to eat the trees.\n",Case,dp[m][n][0]);
}
return 0;
}