hdu 4285 circuits 插头dp
2016-08-23 19:23
302 查看
题目链接
题意:
要求在在给定的n*m(2<=n,m<=12)区域内形成恰好k个回路。使得所有格子均被遍历,(一个格子只能被一个回路遍
历)。并且不能出现一个回路包住另一个回路的情况。问方法总
数。
解法:
要求K个,并不是问题,只要在状态中加入一位存储回路数目即可。12*12/4=36,以8进制来看,大约要留2个8进制位,就是6个二进制位。
然后就是保证不出现环套环的情况:
在回路形成的时候,如果当前格子左边或者右边的轮廓线上有奇数个插头,那么势必插头不能在一边形成回路。一定会有插头左右相连,形成回路时必定包住当前回路。(因为前面不可能有交叉线)
如果对所有插头形成回路时,都保证当前格子左边的轮廓线上有偶数个插头,一定可以保证不形成“环套环”。(因为当前有偶数个插头在左边,如果在下面行有插头跑到右边去了,必然会造成某个回路形成时那一格左边的轮廓线上有奇数个插头)
代码:
#include<cstdio> #include<string> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> #include<vector> using namespace std; #define all(x) (x).begin(), (x).end() #define for0(a, n) for (int (a) = 0; (a) < (n); (a)++) #define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++) #define mes(a,x,s) memset(a,x,(s)*sizeof a[0]) #define mem(a,x) memset(a,x,sizeof a) #define ysk(x) (1<<(x)) typedef long long ll; const int INF =0x3f3f3f3f; const int maxn= 12 ; const int mod=19993; const int N= 1000000 ; int n,m,cur,K; const ll MO=1000000007; struct pll { ll first;ll second; }; int a[maxn+5][maxn+5]; struct Hashmap { pll e ; int fir[mod+3],nex ,nedge; void init() { nedge=0; mem(fir,-1); } void insert(ll state,ll val) { int p=state%mod; for(int i=fir[p];~i;i=nex[i]) { if(state==e[i].first) { e[i].second=(e[i].second+val)%MO; return; } } e[nedge].first=state,e[nedge].second=val; nex[nedge]=fir[p]; fir[p]=nedge++; } }ha[2]; struct Code { int ncircle,tot,bit[maxn+3],ch[maxn+3]; ll s; void decode(ll x) { tot=0; for(int i=0;i<=m;i++) { bit[i]=x&7; tot=max(tot,bit[i]); x>>=3; } tot++; ncircle=x&63;//12*12/4=36>2^3,<2^6 } ll normalize() { mem(ch,-1);ch[0]=0;tot=1; s=ncircle; for(int i=m;i>=0;i--) { if(ch[bit[i]]==-1) ch[bit[i]]=tot++; bit[i]=ch[bit[i]]; s=(s<<3)|bit[i]; } return s; } void shift() { for(int i=m;i>0;i--) bit[i]=bit[i-1]; bit[0]=0; } void color(int a,int b)//a to b { for0(i,m+1) if(bit[i]==a) { bit[i]=b; } } }code; void dpBlock(int x,int y,ll state,ll val) { if(y==m) code.shift(); ha[cur].insert(code.normalize(),val); } void dpBlank(int x,int y,ll state,ll val) { const int p=code.bit[y-1],q=code.bit[y]; if(p&&q) { if(p==q) { if(code.ncircle>=K) return; int t=0; for0(i,y-1) if(code.bit[i]) t++; if(t&1) return; code.ncircle++; code.bit[y-1]=code.bit[y]=0; if(y==m) code.shift(); ha[cur].insert(code.normalize(),val); } else { code.color(p,q); code.bit[y-1]=code.bit[y]=0; if(y==m) code.shift(); ha[cur].insert(code.normalize(),val); } return; } if(!p&&!q) { if(a[x][y+1]&&a[x+1][y]) { code.bit[y-1]=code.bit[y]=code.tot; ha[cur].insert(code.normalize(),val); } return; } int t=p+q; if(a[x][y+1]) { code.bit[y-1]=0,code.bit[y]=t; ha[cur].insert(code.normalize(),val); } if(a[x+1][y]) { code.bit[y-1]=t,code.bit[y]=0; if(y==m) code.shift(); ha[cur].insert(code.normalize(),val); } } void solve() { cur=0; ha[cur].init(); ha[cur].insert(0,1); for1(i,n) for1(j,m) { cur^=1; ha[cur].init(); for0(k,mod) for(int l=ha[cur^1].fir[k];~l;l=ha[1^cur].nex[l]) { pll now=ha[cur^1].e[l]; ll state=now.first,val=now.second; code.decode(state); // if(i==10&&j==10) printf("i=%d,j=%d,state=%lld,val=%lld,code.ncircle=%d\n",i,j,state,val,code.ncircle); if(!a[i][j]) dpBlock(i,j,state,val); else dpBlank(i,j,state,val); } } ll ans=0; for0(k,mod ) for(int l=ha[cur].fir[k];~l;l=ha[cur].nex[l]) { pll now=ha[cur].e[l]; ll state=now.first,val=now.second; code.decode(state); if(code.ncircle==K) ans=(ans+val)%MO; } cout<<ans<<endl; } int main() { std::ios::sync_with_stdio(false); int T;cin>>T;char ch; while(T--) { cin>>n>>m>>K; mem(a,0); for1(i,n) for1(j,m) {cin>>ch;if(ch=='.') a[i][j]=1;} solve(); } return 0; } /* 1233 2 4 2 .... .... 2 6 3 ...... ...... 2 2 1 ## ## 4 4 1 .... .... .... .... 6 6 1 ...... ...... ...... ...... ...... ...... 8 8 1 ........ ........ ........ ........ ........ ........ ........ ........ 4638576 9 9 1 ......... ......... ......... ......... ......... ......... ......... ......... ......... 10 10 1 .......... .......... .......... .......... .......... .......... .......... .......... .......... .......... 12 12 1 ............ ............ ............ ............ ............ ............ ............ ............ ............ ............ ............ ............ */
相关文章推荐
- HDU 4285 circuits( 插头dp , k回路 )
- HDU 4285 circuits[插头DP]
- HDU 4285 circuits(插头DP)
- HDU 4285 circuits(回路不能嵌套的插头DP)
- hdu 4285 circuits(插头DP多条回路无嵌套环)
- HDU 4285 circuits 解题报告(插头DP)
- HDOJ 4285 circuits (插头dp 总结)
- hdu 4285 circuits
- hdu 4064 (插头DP)
- hdu 4285 circuits
- HDU 3377 Plan 解题报告(插头DP)
- HDU 3377 Plan(插头DP-路径最大值)
- HDU 3633 Black and white(插头DP)
- hdu 1693 插头DP
- hdu 1693(插头DP简单题,多条回路)
- HDU 1693 Eat the Trees(插头DP,入门题)
- 插头DP——从不会到入门(POJ 2411,HDU 1565,HDU 2167,HDU 1693,Ural 1519)
- 匹配注意HDU 1693(Eat the Trees-不用匹配的插头Dp)
- HDU-1693-插头dp
- HDU 1693 Eat the Trees(插头DP,多条回路)