HDU-1964 Pipes 插头DP

  题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1964

  空白区域之间有权值,求经过所有空白区域的哈密顿回路的最小权值。简单的插头DP,空白区域特殊处理即可。

  1 //STATUS:C++_AC_203MS_664KB

  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=21,INF=0x3f3f3f3f,MOD=40001,STA=8000010;

 22 const double DNF=1e13;

 23 

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

 25 int T,n,m,ex,ey;

 26 

 27 struct Hash{     //Hash表,MOD为表长,STA为表大小

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

 29     int f[STA];

 30     LL sta[STA];

 31     void init(){

 32         size=0;

 33         mem(first,-1);

 34     }

 35     void add(LL st,int ans){

 36         int i,u=st%MOD;

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

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

 39                 f[i]=Min(f[i],ans);

 40                 return;

 41             }

 42         }

 43         sta[size]=st;

 44         f[size]=ans;

 45         next[size]=first[u];

 46         first[u]=size++;

 47     }

 48 }hs[2];

 49 

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

 51 {

 52     int k;

 53     LL sta;

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

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

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

 57     }

 58 }

 59 

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

 61 {

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

 63     mem(ma,-1);

 64     ma[0]=0;

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

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

 67         code[i]=ma[code[i]];

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

 69     }

 70     return sta;

 71 }

 72 

 73 void getcode(LL sta)

 74 {

 75     int i;

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

 77         code[i]=sta&7;

 78         sta>>=3;

 79     }

 80 }

 81 

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

 83 {

 84     int k,t;

 85     LL cnt,x,y;

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

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

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

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

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

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

 92             if(x!=y){

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

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

 95                 hs[p].add(getsta(),cnt+(g[i][j]<10?g[i][j]:0));

 96             }

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

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

 99             }

100         }

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

102             t=x?x:y;

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

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

105                 hs[p].add(getsta(),cnt+(g[i][j]<10?g[i][j]:0));

106             }

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

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

109                 hs[p].add(getsta(),cnt+(g[i][j]<10?g[i][j]:0));

110             }

111         }

112         else {  //创建新连通分量

113             if(g[i][j]>=0 && g[i][j]<=9){

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

115             }

116             if(g[i+1][j]>=0 && g[i][j+1]>=0){

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

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

119             }

120         }

121     }

122 }

123 

124 void block(LL j,int p)

125 {

126     int k;

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

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

129         if(code[j]==0 && code[j+1]==0)

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

131     }

132 }

133 

134 int slove()

135 {

136     int i,j,p;

137     hs[0].init();

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

139     hs[0].add(0,0);

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

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

142             if(g[i][j]>=0)unblock(i,j,p);

143             else p=!p;

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

145         }

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

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

148     }

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

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

151     return 0;

152 }

153 

154 int main()

155 {

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

157     int i,j,ans;

158     char s[N];

159     scanf("%d",&T);

160     while(T--)

161     {

162         scanf("%d%d",&n,&m);

163         mem(g,-1);

164         n=n*2-1;

165         m=m*2-1;

166         scanf("%s",s);

167         getchar();

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

169             gets(s);

170             for(j=1;j<=m;j++){

171                 if(s[j]==' ')g[i][j-1]=10;

172                 else if(s[j]=='#')g[i][j-1]=-1;

173                 else g[i][j-1]=s[j]-'0';

174             }

175         }

176         scanf("%s",s);

177         ex=n-1,ey=m-1;

178 

179         ans=slove();

180 

181         printf("%d\n",ans);

182     }

183     return 0;

184 }

 

你可能感兴趣的:(HDU)