zoukankan      html  css  js  c++  java
  • 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

    2595: [Wc2008]游览计划

    Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge
    Submit: 1572  Solved: 739

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

    Source

    【分析】

      又是不会的一题啦~

      斯坦纳树?smg?

      刚开始看题可能觉得是最小生成树吧?但是并不是的。

      

      一个条路径可能在最小生成树上面算几次,但是在这题上只算一次。

      然后就是斯坦纳树??【长姿势??

      反正就是,要覆盖的点很少<=10,可以状压这个,f[i][j][t]表示和(i,j)这个格子联通的需覆盖点集合为t的最小代价。

      两个方程:

      $f[i][j][t]=min(f[i][j][s]+f[i][j][t-ss])$ s是t的子集。

      $f[i][j][t]=min(f[x][y][t]+a[i][j])$ (i,j)与(x,y)相邻

      第二个式子啊不是普通的dp啊,转移状态的有环的!!但是,不怕,肯定是小的转到大的,然后一脸最短路的样子,就可以用spfa解决的。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define INF 0xfffffff
      9 
     10 int a[15][15],num[15][15],f[15][15][1500];
     11 
     12 struct node {int x,y,d;};
     13 node g[15][15][1500];
     14 queue<node > q;
     15 bool inq[15][15];
     16 
     17 int bx[6]={0,1,0,-1,0},
     18     by[6]={0,0,1,0,-1};
     19 
     20 void dfs(int x,int y,int k)
     21 {
     22     if(!k) return;inq[x][y]=1;
     23     dfs(g[x][y][k].x,g[x][y][k].y,g[x][y][k].d);
     24     if(g[x][y][k].x==x&&g[x][y][k].y==y) dfs(x,y,k-g[x][y][k].d);
     25 }
     26 
     27 int main()
     28 {
     29     int n,m,cnt=0;
     30     scanf("%d%d",&n,&m);
     31     memset(f,63,sizeof(f));
     32     for(int i=1;i<=n;i++)
     33      for(int j=1;j<=m;j++)
     34      {
     35          scanf("%d",&a[i][j]);
     36          if(a[i][j]==0)
     37          {
     38              num[i][j]=++cnt;
     39              f[i][j][1<<cnt-1]=0;
     40              g[i][j][1<<cnt-1].x=g[i][j][1<<cnt-1].y=g[i][j][1<<cnt-1].d=0;
     41          }
     42      }
     43     for(int i=1;i<=n;i++)
     44      for(int j=1;j<=m;j++) f[i][j][0]=0;
     45     for(int k=1;k<=(1<<cnt)-1;k++)
     46     {
     47         memset(inq,0,sizeof(inq));
     48         for(int ss=k;ss;ss=(ss-1)&k)
     49         {
     50             for(int i=1;i<=n;i++)
     51              for(int j=1;j<=m;j++) //if(a[i][j]==0)
     52              {
     53                  if(f[i][j][k]>f[i][j][ss]+f[i][j][k-ss]-a[i][j])
     54                 {
     55                     f[i][j][k]=f[i][j][ss]+f[i][j][k-ss]-a[i][j];
     56                     node nw;
     57                     nw.x=i;nw.y=j;nw.d=ss;
     58                     g[i][j][k]=nw;
     59                 }
     60                 if(f[i][j][k]<INF) {node nw;nw.x=i;nw.y=j;nw.d=f[i][j][k];inq[i][j]=1;q.push(nw);}
     61              }
     62             
     63         }
     64         while(!q.empty())
     65         {
     66             node x=q.front();
     67             for(int i=1;i<=4;i++)
     68             {
     69                 int nx=x.x+bx[i],ny=x.y+by[i];
     70                 if(nx<1||nx>n||ny<1||ny>m) continue;
     71                 if(f[nx][ny][k]>f[x.x][x.y][k]+a[nx][ny])
     72                 {
     73                     f[nx][ny][k]=f[x.x][x.y][k]+a[nx][ny];
     74                     node nw;
     75                     nw.x=nx;nw.y=ny;//nw.d=f[nx][ny][k];
     76                     // g[nx][ny][k]=g[x.x][x.y][k];
     77                     g[nx][ny][k].x=x.x;g[nx][ny][k].y=x.y;g[nx][ny][k].d=k;
     78                     if(!inq[nx][ny])
     79                     {
     80                         inq[nx][ny]=1;
     81                         q.push(nw);
     82                     }
     83                 }
     84             }
     85             q.pop();inq[x.x][x.y]=0;
     86         }
     87     }
     88     memset(inq,0,sizeof(inq));
     89     bool ok=0;
     90     for(int i=1;i<=n;i++)
     91     {
     92         for(int j=1;j<=m;j++) if(a[i][j]==0)
     93         {
     94             printf("%d
    ",f[i][j][(1<<cnt)-1]);
     95             dfs(i,j,(1<<cnt)-1);
     96             ok=1;break;
     97         }
     98         if(ok) break;
     99     }
    100      
    101     for(int i=1;i<=n;i++)
    102     {
    103         for(int j=1;j<=m;j++)
    104         {
    105             if(a[i][j]==0) printf("x");
    106             else if(inq[i][j]) printf("o");
    107             else printf("_");
    108         }
    109         printf("
    ");
    110     }
    111     return 0;
    112 }
    View Code

    2017-04-05 19:28:31

  • 相关阅读:
    android入门教程(十六)之 使用Intent传递数据
    Android入门教程(十八)之ListView (二) (转)
    Android入门教程(十四)之ListView的应用 (转)
    Android入门教程(十七)之GridView(转自http://blog.csdn.net/hellogv/)
    (原创)Android入门教程(十五)之 Activity生命周期及其配置使用
    Android入门教程(十九)之ListView (三) (转)
    Android入门教程(十三)之自定义下拉菜单模式Spinner与setDropDownViewResource的应用(转)
    Android入门教程(十)之Menu功能菜单设计 (转)
    [vp]ARC059
    欧拉路学习笔记
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6670219.html
Copyright © 2011-2022 走看看