【HDU1693】Eat the Trees(插頭dp)
阿新 • • 發佈:2018-12-09
【HDU1693】Eat the Trees(插頭dp)
題面
HDU
Vjudge
大概就是網格圖上有些點不能走,現在要找到若干條不相交的哈密頓迴路使得所有格子都恰好被走過一遍。
題解
這題的弱化版本吧。。。
因為可以任意分配哈密頓迴路的數量,因此根本不需要再考慮插頭的配對問題了,那麼直接分情況轉移就好啦。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define ll long long #define MAX 13 inline int read() { int x=0;bool t=false;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-')t=true,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return t?-x:x; } int bin[MAX]; ll f[MAX][MAX][1<<12]; int n,m; int g[MAX][MAX]; int main() { int T=read(); bin[0]=1;for(int i=1;i<13;++i)bin[i]=bin[i-1]<<1; for(int TT=1;TT<=T;++TT) { n=read();m=read();memset(g,0,sizeof(g));memset(f,0,sizeof(f)); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) g[i][j]=read(); f[0][m][0]=1;int S=1<<(m+1); for(int i=1;i<=n;++i) { for(int k=0;k<S>>1;++k)f[i][0][k<<1]=f[i-1][m][k]; for(int j=1;j<=m;++j) for(int k=0;k<S;++k) { int left=(k>>(j-1))&1,up=(k>>j)&1; if(!g[i][j]) { if(!left&&!up)f[i][j][k]+=f[i][j-1][k]; continue; } if(!left&&!up) if(g[i+1][j]&&g[i][j+1])f[i][j][k+bin[j-1]+bin[j]]+=f[i][j-1][k]; if(!left&&up) { if(g[i+1][j])f[i][j][k+bin[j-1]-bin[j]]+=f[i][j-1][k]; if(g[i][j+1])f[i][j][k]+=f[i][j-1][k]; } if(left&&!up) { if(g[i+1][j])f[i][j][k]+=f[i][j-1][k]; if(g[i][j+1])f[i][j][k-bin[j-1]+bin[j]]+=f[i][j-1][k]; } if(left&&up)f[i][j][k-bin[j-1]-bin[j]]+=f[i][j-1][k]; } } printf("Case %d: There are %lld ways to eat the trees.\n",TT,f[n][m][0]); } }