1. 程式人生 > >HDU - 1693 Eat the Trees

HDU - 1693 Eat the Trees

題面

題意

給出一張網格圖,用多條迴路覆蓋它的所有格子,問有幾種方案。

做法

插頭dp,在輪廓線上維護這些格子是否與下面的格子相連,並且維護當前的格子是否與左邊的格子相連,也就是維護下面箭頭兩端的格子是否相連:
在這裡插入圖片描述
然後只要用 2 ( n + 1

) 2^(n+1) 的空間複雜度維護它們的連通性,用插頭dp逐格轉移即可。

程式碼

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define N 15
#define M 3000
using namespace std;

ll TT,T,m,n,dp[N][N][M][2];
bool mm[
N][N]; char str[N]; int main() { ll i,j,k; cin>>T; while(T--) { memset(dp,0,sizeof(dp)); scanf("%lld%lld",&m,&n); for(i=1; i<=m; i++) { for(j=1; j<=n; j++) { scanf("%d",&mm[i][j]); } } dp[1][1][0][0]=1; for(i=1; i<=m; i++) { for(j=1; j<=
n; j++) { for(k=0; k<(1 << n); k++) { if(!mm[i][j]) { if(k&(1 << (j-1)) || !dp[i][j][k][0]) continue; if(j<n) dp[i][j+1][k][0]+=dp[i][j][k][0]; else dp[i+1][1][k][0]+=dp[i][j][k][0]; continue; } if(dp[i][j][k][0]) { if(k&(1 << (j-1))) { if(j<n) { dp[i][j+1][k][0]+=dp[i][j][k][0]; dp[i][j+1][k^(1 << (j-1))][1]+=dp[i][j][k][0]; } else dp[i+1][1][k][0]+=dp[i][j][k][0]; } else { if(j<n) dp[i][j+1][k^(1 << (j-1))][1]+=dp[i][j][k][0]; } } if(dp[i][j][k][1]) { if(k&(1 << (j-1))) { if(j<n) dp[i][j+1][k^(1 << (j-1))][0]+=dp[i][j][k][1]; else dp[i+1][1][k^(1 << (j-1))][0]+=dp[i][j][k][1]; } else { if(j<n) { dp[i][j+1][k][1]+=dp[i][j][k][1]; dp[i][j+1][k^(1 << (j-1))][0]+=dp[i][j][k][1]; } else dp[i+1][1][k^(1 << (j-1))][0]+=dp[i][j][k][1]; } } } } } printf("Case %lld: There are %lld ways to eat the trees.\n",++TT,dp[m+1][1][0][0]); } }