zoukankan      html  css  js  c++  java
  • 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
    ",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 }
  • 相关阅读:
    JS事件处理中心的构想
    form的novalidate属性
    AOP思想在JS中的应用
    推行浏览器升级提示,从自己做起
    doT.js模板引擎
    关于JS获取元素宽度的一点儿思考
    类似百度图片,360图片页面的布局插件
    ASCII、Unicode、UTF-8编码关系
    python字符串格式化符号及转移字符含义
    python字符串的方法介绍
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6918277.html
Copyright © 2011-2022 走看看