Ural 1519 Formula 1 插头DP(单回路)

  题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1519

   一条哈密顿回路路,反正是写到蛋疼了,不过终于解决了,插头DP这玩意,太容易出错了,要注意block的处理。

  1 //STATUS:C++_AC_343MS_961KB

  2 #include<stdio.h>

  3 #include<stdlib.h>

  4 #include<string.h>

  5 #include<math.h>

  6 #include<iostream>

  7 #include<string>

  8 #include<algorithm>

  9 #include<vector>

 10 #include<queue>

 11 #include<stack>

 12 #include<map>

 13 using namespace std;

 14 #define LL long long

 15 #define pii pair<int,int>

 16 #define Max(a,b) ((a)>(b)?(a):(b))

 17 #define Min(a,b) ((a)<(b)?(a):(b))

 18 #define mem(a,b) memset(a,b,sizeof(a))

 19 #define lson l,mid,rt<<1

 20 #define rson mid+1,r,rt<<1|1

 21 const int N=15,INF=0x3f3f3f3f,MOD=4001,STA=1000010;

 22 const double DNF=100000000000;

 23 

 24 int g[N][N],code[N],ma[N];

 25 int n,m,ex,ey;

 26 

 27 struct Hash{

 28     int first[MOD],next[STA],size;

 29     LL f[STA],sta[STA];

 30     void init(){

 31         size=0;

 32         mem(first,-1);

 33     }

 34     void add(LL st,LL ans){

 35         int i,u=st%MOD;

 36         for(i=first[u];i!=-1;i=next[i]){

 37             if(sta[i]==st){

 38                 f[i]+=ans;

 39                 return;

 40             }

 41         }

 42         sta[size]=st;

 43         f[size]=ans;

 44         next[size]=first[u];

 45         first[u]=size++;

 46     }

 47 }hs[2];

 48 

 49 void shift(int p)    //换行移位

 50 {

 51     int k;

 52     LL sta;

 53     for(k=0;k<hs[!p].size;k++){

 54         sta=hs[!p].sta[k]<<3;

 55         hs[p].add(sta,hs[!p].f[k]);

 56     }

 57 }

 58 

 59 LL getsta()    //最小表示法

 60 {

 61     LL i,cnt=1,sta=0;

 62     mem(ma,-1);

 63     ma[0]=0;

 64     for(i=0;i<=m;i++){

 65         if(ma[code[i]]==-1)ma[code[i]]=cnt++;

 66         code[i]=ma[code[i]];

 67         sta|=(LL)code[i]<<(3*i);

 68     }

 69     return sta;

 70 }

 71 

 72 void getcode(LL sta)

 73 {

 74     int i;

 75     for(i=0;i<=m;i++){

 76         code[i]=sta&7;

 77         sta>>=3;

 78     }

 79 }

 80 

 81 void unblock(int i,int j,int p)

 82 {

 83     int k,t;

 84     LL cnt,x,y;

 85     for(k=0;k<hs[!p].size;k++){

 86         getcode(hs[!p].sta[k]);

 87         x=code[j],y=code[j+1];

 88         cnt=hs[!p].f[k];

 89         if(x && y){          //合并连通分量

 90             code[j]=code[j+1]=0;

 91             if(x!=y){

 92                 for(t=0;t<=m;t++)

 93                     if(code[t]==y)code[t]=x;

 94                 hs[p].add(getsta(),cnt);

 95             }

 96             else if(i==ex && j==ey){     //最后一个点特殊处理

 97                 hs[p].add(getsta(),cnt);

 98             }

 99         }

100 

101         else if(x&&!y || !x&&y){    //延续连通分量

102             t=x?x:y;

103             if(g[i+1][j]){

104                 code[j]=t;code[j+1]=0;

105                 hs[p].add(getsta(),cnt);

106             }

107             if(g[i][j+1]){

108                 code[j]=0;code[j+1]=t;

109                 hs[p].add(getsta(),cnt);

110             }

111         }

112         else if(g[i+1][j] && g[i][j+1]){   //创建新连通分量

113             code[j]=code[j+1]=8;

114             hs[p].add(getsta(),cnt);

115         }

116     }

117 }

118 

119 void block(LL j,int p)

120 {

121     int k;

122     for(k=0;k<hs[!p].size;k++){

123         getcode(hs[!p].sta[k]);

124         code[j]=code[j+1]=0;

125         hs[p].add(getsta(),hs[!p].f[k]);

126     }

127 }

128 

129 LL slove()

130 {

131     int i,j,p;

132     hs[0].init();

133     hs[p=1].init();

134     hs[0].add(0,1);

135     for(i=0;i<n;i++){

136         for(j=0;j<m;j++){

137             if(g[i][j])unblock(i,j,p);

138             else block(j,p);    //p=!p优化

139             hs[p=!p].init();

140         }

141         shift(p);   //换行移位

142         hs[p=!p].init();

143     }

144     for(i=0;i<hs[!p].size;i++){

145         if(hs[!p].sta[i]==0)return hs[!p].f[i];

146     }

147 

148     return 0;

149 }

150 

151 int main()

152 {

153  //   freopen("in.txt","r",stdin);

154     int i,j;

155     LL ans;

156     char c;

157     while(~scanf("%d%d",&n,&m) && (n || m))

158     {

159         mem(g,0);

160         ex=-1;

161         for(i=0;i<n;i++){

162             for(j=0;j<m;j++){

163                 scanf(" %c",&c);

164                 g[i][j]=(c=='.');

165                 if(g[i][j])ex=i,ey=j;

166             }

167         }

168         if(ex==-1)ans=0;

169         else ans=slove();

170 

171         printf("%I64d\n",ans);

172     }

173     return 0;

174 }

 

你可能感兴趣的:(form)