【BZOJ2595】[Wc2008]游览计划 斯坦纳树
【BZOJ2595】[Wc2008]游览计划
Description
Input
第一行有两个整数,N和 M,描述方块的数目。
接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点;
否则表示控制该方块至少需要的志愿者数目。 相邻的整数用 (若干个) 空格隔开,
行首行末也可能有多余的空格。
Output
由 N + 1行组成。第一行为一个整数,表示你所给出的方案
中安排的志愿者总数目。
接下来 N行,每行M 个字符,描述方案中相应方块的情况:
z ‘_’(下划线)表示该方块没有安排志愿者;
z ‘o’(小写英文字母o)表示该方块安排了志愿者;
z ‘x’(小写英文字母x)表示该方块是一个景点;
注:请注意输出格式要求,如果缺少某一行或者某一行的字符数目和要求不
一致(任何一行中,多余的空格都不允许出现) ,都可能导致该测试点不得分。
Sample Input
0 1 1 0
2 5 5 1
1 5 5 1
0 1 1 0
Sample Output
xoox
___o
___o
xoox
HINT
对于100%的数据,N,M,K≤10,其中K为景点的数目。输入的所有整数均在[0,2^16]的范围内
题解:学了一发斯坦纳树。
用f[S][i][j]表示已经连通的景点状态为S,当前处于(i,j)的最小花费,那么转移方程如下:
f[S][i][j]=min{f[S'][i][j]+f[S^S'][i][j]-a[i][j]}
f[S][i][j]=min{f[S][i'][j']+a[i][j]}
第一个方程相当于枚举子集,而第二个方程存在环,所以采用最短路解决。于是我们先枚举子集,每更新一次都跑一边最短路即可。
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <queue>
- using namespace std;
- int n,m,K,cnt,ans,last;
- int f[1<<10][12][12],v[12][12],pre[1<<10][12][12],inq[12][12],p[12],Log[1<<10],ref[1<<10],vis[12][12];
- int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
- queue<int> qx,qy;
- inline void spfa(int S,int x,int y)
- {
- qx.push(x),qy.push(y);
- int i,tx,ty;
- while(!qx.empty())
- {
- x=qx.front(),y=qy.front(),qx.pop(),qy.pop(),inq[x][y]=0;
- for(i=0;i<4;i++)
- {
- tx=x+dx[i],ty=y+dy[i];
- if(tx>=0&&ty>=0&&tx<n&&ty<m&&f[S][tx][ty]>f[S][x][y]+v[tx][ty])
- {
- f[S][tx][ty]=f[S][x][y]+v[tx][ty],pre[S][tx][ty]=x*m+y;
- if(!inq[tx][ty]) inq[tx][ty]=1,qx.push(tx),qy.push(ty);
- }
- }
- }
- }
- void dfs(int S,int i,int j)
- {
- vis[i][j]=1;
- if(pre[S][i][j]==12345) return ;
- if(pre[S][i][j]<0) dfs(-pre[S][i][j],i,j),dfs(S^(-pre[S][i][j]),i,j);
- else dfs(S,pre[S][i][j]/m,pre[S][i][j]%m);
- }
- int main()
- {
- scanf("%d%d",&n,&m);
- int i,j,x,y;
- memset(f,0x3f,sizeof(f));
- for(i=0;i<n;i++) for(j=0;j<m;j++) scanf("%d",&v[i][j]);
- for(i=0;i<n;i++) for(j=0;j<m;j++) if(!v[i][j]) f[1<<K][i][j]=0,pre[1<<K][i][j]=12345,spfa(1<<K,i,j),K++;
- for(i=0;i<K;i++) Log[1<<i]=i;
- for(x=1;x<(1<<K);x++)
- {
- for(cnt=0,i=x;i;i-=i&-i) p[cnt++]=i&-i;
- for(y=1;y<(1<<cnt);y++)
- {
- ref[y]=ref[y^(y&-y)]|p[Log[y&-y]];
- for(i=0;i<n;i++) for(j=0;j<m;j++) if(f[ref[y]][i][j]+f[x^ref[y]][i][j]-v[i][j]<f[x][i][j])
- f[x][i][j]=f[ref[y]][i][j]+f[x^ref[y]][i][j]-v[i][j],pre[x][i][j]=-ref[y],spfa(x,i,j);
- }
- }
- ans=1<<30;
- for(i=0;i<n;i++) for(j=0;j<m;j++) if(f[(1<<K)-1][i][j]<ans) ans=f[(1<<K)-1][i][j],last=i*m+j;
- dfs((1<<K)-1,last/m,last%m);
- printf("%d\n",ans);
- for(i=0;i<n;i++)
- {
- for(j=0;j<m;j++)
- {
- if(!v[i][j]) putchar('x');
- else if(vis[i][j]) putchar('o');
- else putchar('_');
- }
- puts("");
- }
- return 0;
- }//4 4 0 1 1 0 2 5 5 1 1 5 5 1 0 1 1 0
【BZOJ2595】[Wc2008]游览计划 斯坦纳树的更多相关文章
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- bzoj2595: [Wc2008]游览计划 斯坦纳树
斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...
- BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 2030 Solved: 986[Submit][Status][ ...
- Luogu 4294 [WC2008]游览计划 | 斯坦纳树
题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...
- 【BZOJ-2595】游览计划 斯坦纳树
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1518 Solved: 7 ...
- BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
[题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...
- P4294 [WC2008]游览计划 (斯坦纳树)
题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...
- 洛谷4294 [WC2008]游览计划——斯坦纳树
题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...
- BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...
随机推荐
- DataGridView使用技巧十:单元格表示值的自定义
通过CellFormatting事件,可以自定义单元格的表示值.(比如:值为Error的时候,单元格被设定为红色) 示例: private void dgv_Users_CellFormatting( ...
- 集成vue到jquery/bootstrap项目
说明,项目本身使用jquery和bootstrap做的管理后台,部分登录接口跑在node服务端,大部分接口使用springmvc实现.现在,使用vue开发,集成vue到原先的项目中.不影响原先的框架. ...
- web工程jar包问题
JRE System Library主要存放J2SE的标准jar,一般不需要调整. Referenced Libraries是存放第三方的jar包,也就是自己导入的jar包.在项目属性的Java Bu ...
- javascript删除字符串最后一个字符
搜到很多无用的答案,这对新手来讲是很耗费时间的事情,我把正确的方法贴出来,以便有的新手不再踩这个坑. JavaScript slice() 方法 定义和用法 slice() 方法可提取字符串的某个部分 ...
- C# 在Bitmap上绘制文字出现锯齿的问题
解决锯齿问题主要是修改Graphics的属性 修复绘制图片锯齿问题可以修改 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiA ...
- 一键部署MongoDB集群Windows版
由于周末在家手头没有虚拟机,所以在windows下单机完毕部署要求,并编写bat执行脚本. 1.创建配置文件及相关文件夹 总的启动脚本例如以下(startmc.bat): rem m1 start m ...
- PHPOffice下PHPWord生成Word2007(docx)使用方法
要正常使用,下载依赖包: PhpOffice/Common:https://github.com/PHPOffice/Common Zend/Escaper:https://github.com/ze ...
- 【Java面试题】29 设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1。写出程序。
本题并不难,实现方式有很多种,有很多种结构. 方法一:利用内部类实现,两个实现加减的类实现Runnable接口,然后再实现4个具体线程. 代码: public class ManyThreads { ...
- Spring-DispatcherServlet说明
使用spring MVC,配置DispatcherServlet是第一步. DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet. Dispatc ...
- Linux下的CPU性能瓶颈分析案例
问题描述: 在对notify执行性能测试时发现cpu负载突然飙高,cpu利用率高达95%.这时候就要排查是哪些线程消耗了cpu,并从代码层找到占用cpu的“罪魁祸首”. 步骤: 1. 先用ps+gre ...