bzoj 2595 : [Wc2008]游览计划

2595: [Wc2008]游览计划

Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge
Submit: 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

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]的范围内

 

题解:
斯坦纳树。

$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\n",f[i][j][mx-1]);
115                 dfs(i,j,mx-1);
116                 print();
117                 return 0;
118             }
119         }
120     }
121     return 0;
122 }

 

 

posted @ 2017-03-24 14:47  SD_le  阅读(164)  评论(0编辑  收藏  举报
重置按钮