题目地址:点击打开链接
【题目大意】
一个N*M的方格,有一些点不能访问,求汉密尔顿回路条数
【分析】
裸的插头DP,我代码中是用的括号表示法,而且用排序代替了Hash,这样速度比较快。
【代码】
/*************************
ID:Ciocio
LANG:C++
DATE:2014-1-27
TASK:Ural 1519
*************************/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define MAXN 12
#define MAXSTATE 300000
typedef long long LL;
int N,M,lasti,lastj;
bool mat[MAXN+10][MAXN+10];
int sc,SC;
int s_[MAXSTATE+10],S_[MAXSTATE+10];
LL f_[MAXSTATE+10],F_[MAXSTATE+10];
int* s=s_;
int* S=S_;
LL* f=f_;
LL* F=F_;
char _read(){
char tt=getchar();
while(tt!='*'&&tt!='.') tt=getchar();
return tt;
}
void _qsort(int l,int r){
int i=l,j=r,m=S[(l+r)>>1];
while(i<=j){
while(S[i]<m) i++;
while(S[j]>m) j--;
if(i<=j){
swap(S[i],S[j]);
swap(F[i],F[j]);
i++;j--;
}
}
if(l<j) _qsort(l,j);
if(i<r) _qsort(i,r);
}
void _init(){
cin>>N>>M;
for(int i=0;i<N;i++)
for(int j=0;j<M;j++){
if(_read()=='*')
mat[i][j]=true;
else{
lasti=i;
lastj=j;
}
}
}
int replace(int state,int j,int n){
return (state^(((state>>(j<<1))&3)<<(j<<1)))|(n<<(j<<1));
}
int getp(int state,int j){
return (state>>(j<<1))&3;
}
int getl(int state,int j){
return getp(state,j);
}
int getu(int state,int j){
return getp(state,j+1);
}
int replacedr(int state,int j,int n1,int n2){
return replace(replace(state,j,n1),j+1,n2);
}
void getcl(int state,int j,int& ns){
ns=replacedr(state,j,0,0);
int get=1;
for(int i=j+2;i<=M;i++){
if(getp(ns,i)==1) get++;
else if(getp(ns,i)==2) get--;
if(!get){
ns=replace(ns,i,1);
break;
}
}
}
void getcr(int state,int j,int& ns){
ns=replacedr(state,j,0,0);
int get=1;
for(int i=j-1;i>=0;i--){
if(getp(ns,i)==2) get++;
else if(getp(ns,i)==1) get--;
if(!get){
ns=replace(ns,i,2);
break;
}
}
}
void _solve(){
LL ans=0;
S[SC]=0;
F[SC++]=1;
for(int i=0;i<N;i++){
for(int j=0;j<M;j++){
swap(s,S);
swap(f,F);
sc=SC;SC=0;
if(mat[i][j]){
for(int si=0;si<sc;si++){
int l=getl(s[si],j);
int u=getu(s[si],j);
if(!(l|u)){
S[SC]=s[si];
F[SC++]=f[si];
}
}
}
else{
for(int si=0;si<sc;si++){
int l=getl(s[si],j);
int u=getu(s[si],j);
if(l&&u){
int ns;
if(l==2&&u==1) ns=replacedr(s[si],j,0,0);
else if(l==1&&u==1) getcl(s[si],j,ns);
else if(l==2&&u==2) getcr(s[si],j,ns);
else{
if((!replacedr(s[si],j,0,0))&&i==lasti&&j==lastj) ans+=f[si];
continue;
}
S[SC]=ns;
F[SC++]=f[si];
}
else if(l||u){
int ns;
ns=replacedr(s[si],j,l,u);
S[SC]=ns;
F[SC++]=f[si];
ns=replacedr(s[si],j,u,l);
S[SC]=ns;
F[SC++]=f[si];
}
else{
int ns;
ns=replacedr(s[si],j,1,2);
S[SC]=ns;
F[SC++]=f[si];
}
}
}
_qsort(0,SC-1);
int RSC=0,ii=0;
while(ii<SC){
int jj=ii+1;
while(jj<SC&&S[ii]==S[jj]) F[ii]+=F[jj++];
S[RSC]=S[ii];
F[RSC++]=F[ii];
ii=jj;
}
SC=RSC;
}
int RSC=0,ii=0;
while(ii<SC){
while(ii<SC&&getp(S[ii],M)) ii++;
if(ii<SC){
S[RSC]=S[ii]<<2;
F[RSC++]=F[ii++];
}
}
SC=RSC;
}
cout<<ans<<endl;
}
int main(){
_init();
_solve();
return 0;
}