[WC2008]游览计划(状压dp)
题面太鬼畜不粘了。
题意就是给一张n*m的网格图,每个点有点权,有k个关键点,让你把这k个关键点连成一个联通快的最小代价。
题解
这题nmk都非常小,解法肯定是状压,比较一般的解法插头dp,但不太好写。
但其实这道题是裸的斯坦纳树模型。
斯坦纳树是最小生成树的变形,在一般情况下是NP问题,但在k规模较少时可以用状压dp求解。
我们可以设dp[i][j][s]表示以(i,j)为根,覆盖关键点集合为s时的最小代价。
对于这个状态内部的更新,我们可以对s枚举子集,相当于把联通块拆成两部分再合并起来,dp[i][j][s] <= dp[i][j][S]+dp[i][j][s^S]。其中S是子集。
对于这个状态对外的更新,我们可以对和根有连边的点转移,dp[i'][j'][s']=dp[i][j][s]+a[i][j]。其实令s=s‘也可以,反正到了s‘时也得更新。
这种dp方法的好处就是只保留了一个转移点,降掉了我们枚举转移点的复杂度。
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#define mm make_pair
#define N 11
using namespace std;
queue<pair<int,int> >q;
int ans,dp[N][N][<<],n,m,a[N][N],tot;
bool tag[N][N];
const int dx[]={-,,,};
const int dy[]={,-,,};
struct node{
int x,y,s;
}pre[N][N][<<];
inline void spfa(int x,int y,int s){
q.push(mm(x,y));
while(!q.empty()){
int ux=q.front().first,uy=q.front().second;q.pop();
for(int i=;i<;++i){
int vx=ux+dx[i],vy=uy+dy[i];
if(vx>&&vy>&&vx<=n&&vy<=m);else continue;
if(dp[vx][vy][s]>dp[ux][uy][s]+a[vx][vy]){
dp[vx][vy][s]=dp[ux][uy][s]+a[vx][vy];
pre[vx][vy][s]=node{ux,uy,s};
q.push(mm(vx,vy));
}
}
}
}
inline void findans(int x,int y,int s){
tag[x][y]=;
if(!x||!y)return;
int i=pre[x][y][s].x,j=pre[x][y][s].y,S=pre[x][y][s].s;
if(i==x&&j==y)findans(i,j,S),findans(i,j,s^S);
else findans(i,j,S);
}
int main(){
memset(dp,0x3f,sizeof(dp));
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
for(int j=;j<=m;++j){
scanf("%d",&a[i][j]);
if(!a[i][j])dp[i][j][<<tot]=,tot++;
else dp[i][j][]=a[i][j];
}
int ma=(<<tot)-;
for(int s=;s<=ma;++s){
for(int i=;i<=n;++i)
for(int j=;j<=m;++j){
for(int S=s;S;S=s&(S-))
if(dp[i][j][s]>dp[i][j][S]+dp[i][j][s^S]-a[i][j]){
dp[i][j][s]=dp[i][j][S]+dp[i][j][s^S]-a[i][j];
pre[i][j][s]=node{i,j,S};
}
spfa(i,j,s);
}
}
int ans=2e9,prx,pry;
for(int i=;i<=n;++i)for(int j=;j<=m;++j)
if(dp[i][j][ma]<ans){
ans=min(ans,dp[i][j][ma]);prx=i,pry=j;
}
findans(prx,pry,ma);
cout<<ans<<endl;
for(int i=;i<=n;++i){
for(int j=;j<=m;++j){
if(!a[i][j])printf("x");
else if(tag[i][j])printf("o");
else printf("_");
}
puts("");
}
return ;
}
[WC2008]游览计划(状压dp)的更多相关文章
- luogu4294 [WC2008]游览计划(状压DP/斯坦纳树)
link 题目大意:给定一个网格图,有些点是关键点,选择格点有代价,求把所有关键点联通的最小代价 斯坦纳树模板题 斯坦纳树问题:给定一个图结构,有一些点是关键点,求把这些关键点联通的最小代价e 斯坦纳 ...
- [WC2008]游览计划 状压DP,斯坦纳树
---题面--- 题解: 这是一道斯坦纳树的题,用状压+spfa来解决 什么是斯坦纳树? 一开始还以为是数据结构来着,其实跟最小生成树很像,大致就是最小生成树只能在各个点之间直接相连,而斯坦纳树则允许 ...
- 【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1572 Solved: 7 ...
- BZOJ2595 Wc2008 游览计划 【斯坦纳树】【状压DP】*
BZOJ2595 Wc2008 游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个 ...
- BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】
传送门 题意:略 论文 <SPFA算法的优化及应用> http://www.cnblogs.com/lazycal/p/bzoj-2595.html 本题的核心就是求斯坦纳树: Stein ...
- 【BZOJ2595_洛谷4294】[WC2008]游览计划(斯坦纳树_状压DP)
上个月写的题qwq--突然想写篇博客 题目: 洛谷4294 分析: 斯坦纳树模板题. 简单来说,斯坦纳树问题就是给定一张有边权(或点权)的无向图,要求选若干条边使图中一些选定的点连通(可以经过其他点) ...
- [WC2008]游览计划 解题报告
[WC2008]游览计划 斯坦纳树板子题,其实就是状压dp 令\(dp_{i,s}\)表示任意点\(i\)联通关键点集合\(s\)的最小代价 然后有转移 \[ dp_{i,S}=\min_{T\in ...
- bzoj2595 / P4294 [WC2008]游览计划
P4294 [WC2008]游览计划 斯坦纳树 斯坦纳树,是一种神奇的树.它支持在一个连通图上求包含若干个选定点的最小生成树. 前置算法:spfa+状压dp+dfs(大雾) 我们设$f[o][P]$为 ...
- 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp
题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...
随机推荐
- Mysql drop function xxxx ERROR 1305 (42000): FUNCTION (UDF) xxxx does not exist
mysql> drop function GetEmployeeInformationByID;ERROR 1305 (42000): FUNCTION (UDF) GetEmployeeInf ...
- JavaScript中变量、执行环境、作用域与C#中的异同
首先需要明确一个执行环境的概念,执行环境这个概念是用来理解作用域的,在js中,执行环境分为全局执行环境和局部(function)执行环境,而在C#这类的C类语言中,还有一个块级别的执行环境,如if语句 ...
- [转帖]Kerberos和NTLM - SQL Server
Kerberos和NTLM - SQL Server https://www.cnblogs.com/dreamer-fish/p/3458425.html 当我们使用Windows Authenti ...
- 查找文献的BibTex
BibTex可以通过Google Scholar来查找. 注意,默认情况下,Google scholar 关闭了显示BibTex链接. 打开Google Scholar 选择右上角菜单按钮 选择set ...
- 单个源文件下CmakeList.txt
单个源文件下CmakeList.txt 1. main.c代码 & CmakeLists.txt 文件内容 在任意自己选定的目录下(t1/)编写main.c 与 CmakeLists.txt ...
- Laravel技巧:使用load、with预加载 区别
1.使用load $posts = Post::all(); $posts->load('user'); 2.使用with $posts = Post::with('user')->all ...
- hive条件函数
case相当于if,when相当于=:then是条件满足的结论.否则实行else后语句,一end结束
- Numpy中array数据操作
1.创建: import numpy as np arr=np.array([1,2,3]) print(arr,arr.ndim) list=[1,2,3] arr=np.array(list) 2 ...
- Saltstack 安装与常用模块
一.介绍 saltstack是基于C/S服务模式,在该架构中,服务器端叫做Master,客户端叫做Minion.传统的C/S模式我们这样理解,客户端发送请求给服务器端,服务器端接受到来自客户端的请求并 ...
- JS检测是否是360浏览器
// JavaScript Document //application/vnd.chromium.remoting-viewer 可能为360特有 var is360 = _mime("t ...