题面在这里
题意
四通格内有部分格子为障碍物,求用数个回路将非障碍物格子全部覆盖的方案数
数据范围
[1le n,mle 11
]
sol
本人插头DP第一题
入门首推CDQ大佬论文《基于连通性状态压缩的动态规划问题》
插头指两个相邻元素之间是否相连的性质,
而插头DP以轮廓线上各个插头的状态,
转移时主要按格转移,需要相当的时间讨论转移方程,
因此是一种非常难写的状态压缩DP...
这道题轮廓线上只要维护是否联通,也就是0/1两个状态,
最后只要匹配完所有的插头就合法,稍微注意一下障碍物就行。
其实没有学过插头DP的大佬们也是可以做出这种多回路问题的
代码
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<iomanip>
#include<cstring>
#include<complex>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define RG register
#define il inline
using namespace std;
typedef unsigned long long ull;
typedef vector<int>VI;
typedef long long ll;
typedef double dd;
const dd eps=1e-10;
const int mod=1e8;
const int N=13;
il ll read(){
RG ll data=0,w=1;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
return data*w;
}
il void file(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
}
int T,c,mp[N][N];ll f[N][N][1<<N];
il void solve(){
RG int n=read(),m=read(),p,q;
for(RG int i=1;i<=n;i++)
for(RG int j=1;j<=m;j++)mp[i][j]=read();
memset(f,0,sizeof(f));f[1][1][0]=1;
for(RG int i=1;i<=n;i++)
for(RG int j=1;j<=m;j++){
p=1<<(j-1);q=1<<j;
if(j==m){
if(!mp[i][j])
for(RG int k=0;k<(1<<(m+1));k++){
if(!(k&p)&&!(k&q))
f[i+1][1][k<<1]+=f[i][j][k];
}
else
for(RG int k=0;k<(1<<(m+1));k++)
if((k&p)&&!(k&q))
f[i+1][1][k<<1]+=f[i][j][k];
else if(!(k&p)&&(k&q))
f[i+1][1][((k^q)|p)<<1]+=f[i][j][k];
else if((k&p)&&(k&q))
f[i+1][1][((k^q)^p)<<1]+=f[i][j][k];
continue;
}
if(!mp[i][j]){
for(RG int k=0;k<(1<<(m+1));k++)
if(!(k&p)&&!(k&q))f[i][j+1][k]+=f[i][j][k];
}
else {
for(RG int k=0;k<(1<<(m+1));k++)
if((k&p)&&(k&q))
f[i][j+1][(k^p)^q]+=f[i][j][k];
else if((k&p)&&!(k&q)){
f[i][j+1][(k^p)|q]+=f[i][j][k];
f[i][j+1][k]+=f[i][j][k];
}
else if(!(k&p)&&(k&q)){
f[i][j+1][(k|p)^q]+=f[i][j][k];
f[i][j+1][k]+=f[i][j][k];
}
else f[i][j+1][(k|p)|q]+=f[i][j][k];
}
}
printf("Case %d: There are %lld ways to eat the trees.
",++c,f[n+1][1][0]);
}
int main()
{
T=read();while(T--)solve();return 0;
}