BZOJ2595 [Wc2008]游览计划


Solution

考虑这是一个最小费用连通性的问题,既然大家都说这是什么斯坦纳树那就是的吧...

所以我们肯定可以这样设一个dp状态:

\(dp_{i,j,k}\)表示经过点(i,j)且现在连通性为\(k\)的最小费用.

有两种转移方程:

  1. \(dp_{i,j,k}=dp_{i,j,s}+dp_{i,j,k-s}-a[i][j];\)

  2. \(dp_{i,j,k}=dp_{x,y,k}+a[i][j]\)

这个还是比较显然?

发现后面那个东西很像最短路不是吗?

直接SPFA+dp转移一下就好了.

代码实现

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<iostream>
using namespace std;
#define ll long long
#define re register
#define file(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
inline int gi()
{
    int f=1,sum=0;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
    return f*sum;
}
const int N=20,Inf=1e9;
int bin[N],f[12][12][1024],vis[N][N];
int wa[4]={1,0,-1,0};
int lk[4]={0,1,0,-1};
struct node{
    int a,b,c;
}pre[12][12][60010];
int a[N][N],n,m,b[N][N];
typedef pair<int,int> pii;
#define mp make_pair
queue<pii>Q;
void spfa(int s){
    while(!Q.empty()){
        pii now=Q.front();Q.pop();
        int x=now.first,y=now.second;vis[x][y]=0;
        for(int i=0;i<4;i++){
            int xx=x+wa[i],yy=y+lk[i];
            if(xx<1 || xx>n || yy<1 || yy>m)continue;
            if(f[xx][yy][s]>f[x][y][s]+a[xx][yy]){
                f[xx][yy][s]=f[x][y][s]+a[xx][yy];
                pre[xx][yy][s]=(node){x,y,s};
                if(!vis[xx][yy]){
                    vis[xx][yy]=1;Q.push(mp(xx,yy));
                }
            }
        }
    }
}
void dfs(int i,int j,int s)
{
    if(i>=Inf || pre[i][j][s].c==0)return;
    b[i][j]=1;node q=pre[i][j][s];
    dfs(q.a,q.b,q.c);
    if(q.a==i && q.b==j)dfs(i,j,s-q.c);
}
int main()
{
    int K=0;
    bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;
    n=gi();m=gi();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            a[i][j]=gi();
            if(!a[i][j])K++;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<bin[K];k++)
                f[i][j][k]=pre[i][j][k].a=Inf;
    K=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(!a[i][j])
                f[i][j][bin[K]]=0,K++;
    for(int s=1;s<bin[K];s++){
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                for(int ss=s&(s-1);ss;ss=s&(ss-1)){
                    int t=f[i][j][ss]+f[i][j][s-ss]-a[i][j];
                    if(t<f[i][j][s]){
                        f[i][j][s]=t;pre[i][j][s]=(node){i,j,ss};
                    }
                }
                if(f[i][j][s]<Inf){
                    Q.push(mp(i,j));vis[i][j]=1;
                }
            }
        spfa(s);
    }
    int x=0,y;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            if(!a[i][j]){
                x=i;y=j;break;
            }
        if(x)break;
    }
    dfs(x,y,bin[K]-1);
    printf("%d\n",f[x][y][bin[K]-1]);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            if(!a[i][j])putchar('x');
            else if(b[i][j])putchar('o');
            else putchar('_');
        putchar('\n');
    }
    return 0;
}

【BZOJ2595】 [Wc2008]游览计划的更多相关文章

  1. BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*

    BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...

  2. [bzoj2595][WC2008]游览计划/[bzoj5180][Baltic2016]Cities_斯坦纳树

    游览计划 bzoj-2595 wc-2008 题目大意:题目链接.题目连接. 注释:略. 想法:裸题求斯坦纳树. 斯坦纳树有两种转移方式,设$f[s][i]$表示联通状态为$s$,以$i$为根的最小代 ...

  3. BZOJ2595 WC2008游览计划(斯坦纳树)

    斯坦纳树板子题. 考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案. 转移时首先枚举子集,有f[i][j][S]=min{f[i][j ...

  4. BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】

    题目链接 BZOJ2595 题解 著名的斯坦纳树问题 设\(f[i][j][s]\)表示点\((i,j)\)与景点联通状况为\(s\)的最小志愿者数 设\(val[i][j]\)为\((i,j)\)需 ...

  5. bzoj2595 [Wc2008]游览计划——斯坦纳树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...

  6. BZOJ2595[WC2008]游览计划

    Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数 ...

  7. 斯坦纳树 [bzoj2595][wc2008]游览计划 题解

    话说挺早就写过斯坦纳树了,不过当时没怎么总结,也不是很理解……现在来个小结吧~ 斯坦纳树就是包含给定点的最小生成树(个人理解权值应当为正). 一般来讲,给定点的数目应该很小吧...于是我们可以用状压D ...

  8. bzoj2595: [Wc2008]游览计划 斯坦纳树

    斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...

  9. BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)

    Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 2030  Solved: 986[Submit][Status][ ...

随机推荐

  1. 纯H5+c3实现表单验证

    客户端验证是网页客户端程序最常用的功能之一,我们之前使用了各种各样的js库来进行表单的验证.HTML5其实早已为我们提供了表单验证的功能.至于为啥没有流行起来估计是兼容性的问题还有就是样式太丑陋了吧. ...

  2. 使用 CXF 做 webservice 简单例子(转载)

    使用 CXF 做 webservice 简单例子     Apache CXF 是一个开放源代码框架,提供了用于方便地构建和开发 Web 服务的可靠基础架构.它允许创建高性能和可扩展的服务,您可以将这 ...

  3. mysql 5.7 linux环境下解压安装

    在CentOS linux环境安装mysql 一般rpm(或者yum),预编译和源码安装. 如果采用rpm或者yum安装,mysql的数据文件一般存放在/var/lib/mysql目录下,也就是会把d ...

  4. mysql字符集调整总结

    字符集是一套符号和编码的规则,不论是在oracle数据库还是在mysql数据库,都存在字符集的选择问题.对于数据库来说,字符集又是比较重要的,因为数据库存储的数据大部分都是各种文字,字符集对于数据库的 ...

  5. NOIP水题测试(2017082501)

    日常水题测试又来了! 以后答案都以单题形式公布. 下面看今天的水题: 时间限制:5小时 题目一:无法形容的水 题目二:比上一题还水 题目三:一元三次方程求解 题目四:单词接龙 题目五:统计单词个数 题 ...

  6. JS高级-***Function- ***OOP

    1. ***Function 作用域(scope): 什么是: 一个变量的使用范围 为什么: 避免函数内外的变量间互相影响 包括: 2种: 1. 全局作用域: window 保存着全局变量: 随处可用 ...

  7. linux下面/usr/local和opt目录有何区别

    /usr/local下一般是你安装软件的目录,这个目录就相当于在windows下的programefiles这个目录 .很多应用都安装在/usr/local下面,那么,这些应用为什么选择这个目录呢?答 ...

  8. python之函数篇3

    一:函数的定义 1)函数的简单使用,无参函数 def f1(): # 定义函数指定函数名 print("hello") # 指定功能 f1() # 调用函数,才能执行函数体里面的功 ...

  9. rbenv安装本地ruby安装包

    cd .rbenv mkdir cache #把安装包拷进cache cd cache rbenv install 版本号

  10. django之补充

    一 QuerySet类型 QuerySet类型:只和orm有关,如果一涉及数据库,就会有QuerySet类型的出现. QuerySet切片操作:QuerySet是支持切片操作的,不过不能放负数.查询集 ...