• 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
    ",f[i][j][mx-1]);
    115                 dfs(i,j,mx-1);
    116                 print();
    117                 return 0;
    118             }
    119         }
    120     }
    121     return 0;
    122 }
  • 相关阅读:
    day5-装饰器的正确打开方式------------->懒
    python_day5--->递归函数,二分法查找
    day4_生成器yield
    day4_迭代器
    day4_装饰器
    day4_函数嵌套和闭包以及作用域
    this作用域,改变作用域的方法
    $.ajax传数据.php
    ul标签的引用
    URL
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6611465.html
Copyright © 2020-2023  润新知