首页 > 代码库 > bzoj2595 [Wc2008]游览计划

bzoj2595 [Wc2008]游览计划

Description

技术分享

技术分享

Input

第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。

Output

由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z  ‘_’(下划线)表示该方块没有安排志愿者;
z  ‘o’(小写英文字母o)表示该方块安排了志愿者;
z  ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。

Sample Input

4 4
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0

Sample Output

6
xoox
___o
___o
xoox

HINT

 对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内

 

正解:斯坦纳树。

$thusc$的$day1t1$考了斯坦纳树,但是我没学啊,于是$gg$。。

斯坦纳树大概就是求一个连通图满足某些鬼畜条件的生成树??其实似乎挺简单的样子。。

比如这题,我们要求使得所有关键点连通的最小生成树,那么我们可以把这些关键点状压起来。

设$f[i][j][s]$,表示以点$(i,j)$为根,关键点状态为$s$的最小生成树。

那么,每一层$s$内,我们先枚举$s$的子集,$f[i][j][s]=min(f[i][j][s],f[i][j][sub]+f[i][j][s-sub]-g[i][j])$,$g[i][j]$为当前根的权值。很显然,根算了两次,所以我们要减掉。

子集转移完以后,我们可以用$spfa$来松弛整层,$f[i][j][s]=min(f[i][j][s],f[p][q][s]+dis(i,j,p,q))$。

最后某个关键点的全集状态$f[i][j][S]$就是答案了。。然后这题要输出方案,我们记录前驱,搜索一下状态树就好了。

 

  1 //It is made by wfj_2048~  2 #include <algorithm>  3 #include <iostream>  4 #include <complex>  5 #include <cstring>  6 #include <cstdlib>  7 #include <cstdio>  8 #include <vector>  9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define all (1<<k) 16 #define il inline 17 #define RG register 18 #define ll long long 19   20 using namespace std; 21   22 const int d1[4]={1,0,-1,0}; 23 const int d2[4]={0,1,0,-1}; 24   25 int pre[12][12][1<<11][3],f[12][12][1<<11],a[12][12],g[12][12],vis[12][12],q1[100010],q2[100010],n,m,k; 26   27 il int gi(){ 28     RG int x=0,q=1; RG char ch=getchar(); 29     while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 30     if (ch==-) q=-1,ch=getchar(); 31     while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 32     return q*x; 33 } 34   35 il void dfs(RG int x,RG int y,RG int s){ 36     if (!x || !y) return; a[x][y]=1,dfs(pre[x][y][s][0],pre[x][y][s][1],pre[x][y][s][2]); 37     if (pre[x][y][s][0]==x && pre[x][y][s][1]==y) dfs(x,y,s^pre[x][y][s][2]); return; 38 } 39   40 il void spfa(RG int s){ 41     RG int h=0,t=0; 42     for (RG int i=1;i<=n;++i) 43     for (RG int j=1;j<=m;++j) 44         if (f[i][j][s]!=f[0][0][0]) q1[++t]=i,q2[t]=j,vis[i][j]=1; 45     while (h<t){ 46     RG int x=q1[++h],y=q2[h],nowx,nowy; 47     for (RG int i=0;i<4;++i){ 48         nowx=x+d1[i],nowy=y+d2[i]; 49         if (!nowx || !nowy || nowx>n || nowy>m) continue; 50         if (f[nowx][nowy][s]>f[x][y][s]+g[nowx][nowy]){ 51         f[nowx][nowy][s]=f[x][y][s]+g[nowx][nowy],pre[nowx][nowy][s][0]=x; 52         pre[nowx][nowy][s][1]=y,pre[nowx][nowy][s][2]=s; 53         if (!vis[nowx][nowy]) vis[nowx][nowy]=1,q1[++t]=nowx,q2[t]=nowy; 54         } 55     } 56     vis[x][y]=0; 57     } 58     return; 59 } 60   61 il void work(){ 62     n=gi(),m=gi(),memset(f,0x3f3f3f,sizeof(f)); 63     for (RG int i=1;i<=n;++i) 64     for (RG int j=1;j<=m;++j){ 65         g[i][j]=gi(); 66         if (!g[i][j]) f[i][j][1<<(k++)]=0; 67     } 68     if (!k){ 69     puts("0"); 70     for (RG int i=1;i<=n;++i){ 71         for (RG int j=1;j<=m;++j) printf("_"); puts(""); 72     } 73     return; 74     } 75     for (RG int s=1;s<all;++s){ 76     for (RG int i=1;i<=n;++i) 77         for (RG int j=1;j<=m;++j){ 78         for (RG int sub=(s-1)&s;sub;sub=(sub-1)&s){ 79             if (f[i][j][sub]==f[0][0][0] || f[i][j][s^sub]==f[0][0][0]) continue; 80             RG int now=f[i][j][sub]+f[i][j][s^sub]-g[i][j]; 81             if (f[i][j][s]>now) f[i][j][s]=now,pre[i][j][s][0]=i,pre[i][j][s][1]=j,pre[i][j][s][2]=sub; 82         } 83         } 84     spfa(s); 85     } 86     for (RG int i=1;i<=n;++i) 87     for (RG int j=1;j<=m;++j){ 88         if (g[i][j]) continue; printf("%d\n",f[i][j][all-1]),dfs(i,j,all-1); 89         for (RG int i=1;i<=n;++i){ 90         for (RG int j=1;j<=m;++j) 91             if (!g[i][j]) printf("x"); 92             else if (a[i][j]) printf("o"); 93             else printf("_"); 94         puts(""); 95         } 96         return; 97     } 98     return; 99 }100  101 int main(){102     work();103     return 0;104 }

 

bzoj2595 [Wc2008]游览计划