2595: [Wc2008]游览计划
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 586 Solved: 212
[Submit][Status]
Description
Input
第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。
Output
由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z ‘_’(下划线)表示该方块没有安排志愿者;
z ‘o’(小写英文字母o)表示该方块安排了志愿者;
z ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。
Sample Input
Sample Output
HINT
对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内
题解:
斯坦纳树。
$f[i][j]$表示以点$i$为根,与景点连通性至少为$j$的最小花费。
两种转移:
$f[i][j]=min(f[i][k]+f[i][j-k]-a[i][j])$
$f[i][j]=min(f[k][j]+a[i][j])$k与i相邻。
第二种转移可以在求完一个s之后用spfa一起转移,相当于求超级原点到每个点的最短路。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define inf 0x3f3f3f3f 7 #define N 12 8 using namespace std; 9 int n,m; 10 int a[N][N]; 11 int st[N][N],ks; 12 int f[N][N][1<<11],in[N][N],pre[N][N][1<<11][3]; 13 struct node 14 { 15 int x,y; 16 node(int _x,int _y) 17 { 18 x=_x;y=_y; 19 } 20 }; 21 queue<node>q; 22 int k1[]={0,0,1,-1}; 23 int k2[]={1,-1,0,0}; 24 void spfa(int s) 25 { 26 while(!q.empty()) 27 { 28 node tmp=q.front();q.pop();in[tmp.x][tmp.y]=0; 29 for(int i=0;i<4;i++) 30 { 31 int xx=tmp.x+k1[i],yy=tmp.y+k2[i]; 32 if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&f[xx][yy][s]>f[tmp.x][tmp.y][s]+a[xx][yy]) 33 { 34 f[xx][yy][s]=f[tmp.x][tmp.y][s]+a[xx][yy]; 35 pre[xx][yy][s][0]=tmp.x;pre[xx][yy][s][1]=tmp.y;pre[xx][yy][s][2]=s; 36 if(!in[xx][yy]) 37 { 38 q.push(node(xx,yy)); 39 in[xx][yy]=1; 40 } 41 } 42 } 43 } 44 return ; 45 } 46 bool v[N][N]; 47 void dfs(int x,int y,int s) 48 { 49 // cout<<x<<' '<<y<<endl; 50 if(!s)return ; 51 v[x][y]=1; 52 dfs(pre[x][y][s][0],pre[x][y][s][1],pre[x][y][s][2]); 53 if(pre[x][y][s][0]==x&&pre[x][y][s][1]==y) 54 { 55 dfs(x,y,s^pre[x][y][s][2]); 56 } 57 return ; 58 } 59 void print() 60 { 61 for(int i=1;i<=n;i++) 62 { 63 for(int j=1;j<=m;j++) 64 { 65 if(!a[i][j])putchar('x'); 66 else if(v[i][j])putchar('o'); 67 else putchar('_'); 68 }puts(""); 69 } 70 } 71 int main() 72 { 73 scanf("%d%d",&n,&m); 74 memset(f,0x3f,sizeof(f)); 75 for(int i=1;i<=n;i++) 76 { 77 for(int j=1;j<=m;j++) 78 { 79 scanf("%d",&a[i][j]); 80 if(!a[i][j]) 81 { 82 st[i][j]=(1<<ks); 83 ks++; 84 f[i][j][st[i][j]]=0; 85 } 86 } 87 } 88 int mx=1<<ks; 89 for(int s=1;s<mx;s++) 90 { 91 for(int i=1;i<=n;i++) 92 { 93 for(int j=1;j<=m;j++) 94 { 95 for(int k=(s-1)&s;k;k=(k-1)&s) 96 { 97 if(f[i][j][k]+f[i][j][s-k]-a[i][j]<f[i][j][s]) 98 { 99 f[i][j][s]=f[i][j][k]+f[i][j][s-k]-a[i][j]; 100 pre[i][j][s][0]=i;pre[i][j][s][1]=j;pre[i][j][s][2]=k; 101 } 102 } 103 if(f[i][j][s]<inf)q.push(node(i,j)) ; 104 } 105 } 106 spfa(s); 107 } 108 for(int i=1;i<=n;i++) 109 { 110 for(int j=1;j<=m;j++) 111 { 112 if(!a[i][j]) 113 { 114 printf("%d ",f[i][j][mx-1]); 115 dfs(i,j,mx-1); 116 print(); 117 return 0; 118 } 119 } 120 } 121 return 0; 122 }