很久以前就想做,后来弃坑了。
最近又在群里有人问了类似的问题,艾老师说是斯坦纳树(%%%)
就是状压DP,然后用Spfa对状态进行转移.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 2 #include <iostream> 3 #include <cstring> 4 #include <cstdio> 5 #include <algorithm> 6 #include <queue> 7 using namespace std; 8 const int Maxn=15; 9 const int Maxm=1030; 10 const int Inf=0x3f3f3f3f; 11 const int Px=102501; 12 const int Py=1024; 13 const int dx[]={0,0,1,-1}; 14 const int dy[]={1,-1,0,0}; 15 //================================== 16 int n,m,K,Sta,g[Maxn][Maxn],f[Maxn][Maxn][Maxm],pre[Maxn][Maxn][Maxm],STA[Maxn][Maxn]; 17 bool used[1200130],Ans[Maxn][Maxn]; 18 queue<int> Q; 19 inline int Calc(int x,int y,int s) {return x*Px+y*Py+s;} 20 inline bool Check(int a,int b) {return (a|b)==a;} 21 inline bool Judge(int x,int y) {return (x>=1 && x<=n) && (y>=1 && y<=m);} 22 void Spfa(int sta) 23 { 24 while (!Q.empty()) 25 { 26 int u=Q.front(); Q.pop(); 27 int x=u/Px,y=u%Px/Py; 28 for (int d=0;d<4;d++) 29 { 30 int p=x+dx[d],q=y+dy[d]; 31 int r=sta|STA[p][q]; 32 if (!Judge(p,q)) continue; 33 if (f[p][q][r]>f[x][y][sta]+g[p][q]) 34 { 35 f[p][q][r]=f[x][y][sta]+g[p][q]; 36 pre[p][q][r]=u; 37 int k=Calc(p,q,r); 38 if (!used[k] && sta==r) used[k]=true,Q.push(k); 39 } 40 } 41 used[u]=false; 42 } 43 } 44 45 void Init(int x,int y,int sta) 46 { 47 Ans[x][y]=true; 48 int k=pre[x][y][sta]; 49 if (!k) return; 50 int i=k/Px,j=k%Px/Py,s=k%Px%Py; 51 Init(i,j,s); 52 if (i==x && j==y) Init(i,j,sta-s); 53 } 54 55 void Out() 56 { 57 for (int i=1;i<=n;i++) 58 { 59 for (int j=1;j<=m;j++) 60 if (Ans[i][j]) 61 if (g[i][j]) putchar('o'); else putchar('x'); 62 else putchar('_'); 63 putchar('\n'); 64 } 65 } 66 67 68 int main() 69 { 70 scanf("%d%d",&n,&m); 71 for (int i=1;i<=n;i++) 72 for (int j=1;j<=m;j++) 73 for (int k=0;k<=(1<<10);k++) f[i][j][k]=Inf; 74 75 for (int i=1;i<=n;i++) 76 for (int j=1;j<=m;j++) 77 { 78 scanf("%d",&g[i][j]); 79 if (!g[i][j]) STA[i][j]=(1<<(K++)),f[i][j][STA[i][j]]=0; 80 } 81 Sta=(1<<K); 82 for (int sta=1;sta<Sta;sta++) 83 { 84 for (int i=1;i<=n;i++) 85 for (int j=1;j<=m;j++) 86 { 87 for (int s=1;s<sta;s++) 88 if (Check(sta,s)) 89 if (f[i][j][sta]>f[i][j][s]+f[i][j][sta-s]-g[i][j]) 90 f[i][j][sta]=f[i][j][s]+f[i][j][sta-s]-g[i][j], 91 pre[i][j][sta]=Calc(i,j,s); 92 if (f[i][j][sta]!=Inf) 93 Q.push(Calc(i,j,sta)),used[Calc(i,j,sta)]=true; 94 } 95 Spfa(sta); 96 } 97 98 for (int i=1;i<=n;i++) 99 for (int j=1;j<=m;j++) 100 if (!g[i][j]) 101 { 102 printf("%d\n",f[i][j][Sta-1]); 103 Init(i,j,Sta-1); 104 Out(); 105 return 0; 106 } 107 return 0; 108 } 109