這題顯然是一個最小斯坦納樹的模型,直接上模板即可,就是正六邊形比較噁心。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define rep(i,n) for(int i=0;i<n;i++) #define INF 0x3f3f3f3f using namespace std; const int N=1610,M=9610; typedef pair<int,int>P; int R,n,m,k=4,f[N][1<<4],st[N],all=1<<k,ans,g[N],to[M],nxt[M],cost[N],e,id[41][41]; bool vis[N][1<<4]; queue<int>Q; int read(){ char ch; while(!(((ch=getchar())=='A')||(ch=='B')||(ch=='C')||(ch=='D')||(ch=='.'))); return ch=='.'?4:ch-'A'; } void add(int u,int v){to[e]=v;nxt[e]=g[u];g[u]=e++;} void add(int u,int x,int y){ if(x<0||y<0||x>=m||y>=m)return; if(~id[x][y]&&id[x][y]!=u)add(u,id[x][y]); } void spfa(int S){ while(!Q.empty()){ int u=Q.front();Q.pop(); vis[u][S]=false; for(int p=g[u];~p;p=nxt[p]){ int v=to[p]; int w=cost[v]; if(f[v][st[v]|S]>f[u][S]+w){ f[v][st[v]|S]=f[u][S]+w; if(st[v]|S!=S||vis[v][S])continue; vis[v][S]=1; Q.push(v); } } } } void solve(){ memset(g,-1,sizeof g); while(!Q.empty())Q.pop(); e=0;n=k;m=R*2-1; rep(i,m)rep(j,m)id[i][j]=-1; rep(i,R-1)rep(j,R+i){ int x=read(); if(x<k)cost[id[i][j]=x]=0;else cost[id[i][j]=n++]=1; } rep(i,R)rep(j,m-i){ int x=read(); if(x<k)cost[id[R+i-1][j]=x]=0;else cost[id[R+i-1][j]=n++]=1; } rep(i,m)rep(j,m)if(~id[i][j]){ add(id[i][j],i,j-1); add(id[i][j],i,j+1); if(i<R-1){ add(id[i][j],i-1,j-1); add(id[i][j],i-1,j); add(id[i][j],i+1,j); add(id[i][j],i+1,j+1); }else if(i==R-1){ add(id[i][j],i-1,j-1); add(id[i][j],i-1,j); add(id[i][j],i+1,j-1); add(id[i][j],i+1,j); }else{ add(id[i][j],i-1,j); add(id[i][j],i-1,j+1); add(id[i][j],i+1,j-1); add(id[i][j],i+1,j); } } rep(i,n)rep(j,all)f[i][j]=INF; memset(st,0,sizeof st); memset(vis,0,sizeof vis); rep(i,k)st[i]=1<<i,f[i][st[i]]=0; for(int j=1;j<all;j++){ rep(i,n){ if(st[i]&&(st[i]&j)==0)continue; for(int sub=(j-1)&j;sub;sub=(sub-1)&j){ int x=st[i]|sub,y=st[i]|(j-sub); f[i][j]=min(f[i][j],f[i][x]+f[i][y]-cost[i]); } if(f[i][j]<INF){ Q.push(i); vis[i][j]=true; } } spfa(j); } ans=INF; rep(j,n)ans=min(ans,f[j][all-1]); printf("You have to buy %d parcels.\n",ans); } int main(){ while(scanf("%d",&R),R)solve(); return 0; }