BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树
【题目分析】
斯坦纳树=子集DP+SPFA?
用来学习斯坦纳树的模板。
大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态。
更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即可。
【代码】
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath> #include <set>
#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue> using namespace std; #define maxn 11
#define F(i,j,k) for (int i=j;i<=k;++i)
#define inf (0x3f3f3f3f) int Getint()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
} int n,m,a[maxn][maxn],cnt=0,dp[maxn][maxn][1<<maxn],pre[maxn][maxn][1<<maxn][4];
queue <int> qi,qj;
int inq[maxn][maxn],b[maxn][maxn];
int mov[4][2]={0,1,1,0,-1,0,0,-1}; void dfs(int x,int y,int k)
{
// cout<<"dfs "<<x<<" "<<y<<" "<<k<<endl;
// getchar();
if (!k||!x||!y) return;
b[x][y]=1;
dfs(pre[x][y][k][0],pre[x][y][k][1],pre[x][y][k][2]);
if (pre[x][y][k][2]!=k) dfs(pre[x][y][k][0],pre[x][y][k][1],k^pre[x][y][k][2]);
// if (pre[x][y][k][0]==x&&pre[x][y][k][1]==y) dfs(pre[x][y][k][0],pre[x][y][k][1],k^pre[x][y][k][2]);
} void out()
{
F(i,1,n)
{
F(j,1,m)
if (b[i][j])
{
if (a[i][j]) printf("o");
else printf("x");
}
else
{
printf("_");
}
printf("\n");
}
} int main()
{
memset(dp,0x3f,sizeof dp);
n=Getint();m=Getint();
F(i,1,n) F(j,1,m)
{
a[i][j]=Getint();
if(!a[i][j])
{
cnt++;
dp[i][j][1<<(cnt-1)]=0;
}
}
for (int k=1;k<(1<<cnt);++k)
{
F(i,1,n) F(j,1,m)
{
for (int x=(k-1)&k;x;x=(x-1)&k)
{
int tmp=dp[i][j][x]+dp[i][j][k^x]-a[i][j];
if (tmp<dp[i][j][k])
{
dp[i][j][k]=tmp;
pre[i][j][k][0]=i;
pre[i][j][k][1]=j;
pre[i][j][k][2]=x;
}
}
if (dp[i][j][k]<inf)
{
qi.push(i);
qj.push(j);
inq[i][j]=1;
}
}
while (!qi.empty())
{
int ni=qi.front(),nj=qj.front();
qi.pop();qj.pop();
inq[ni][nj]=0;
F(i,0,3)
{
int ti=ni+mov[i][0],tj=nj+mov[i][1];
if (ti<=0||ti>n||tj<=0||tj>m) continue;
if (dp[ni][nj][k]+a[ti][tj]<dp[ti][tj][k])
{
dp[ti][tj][k]=dp[ni][nj][k]+a[ti][tj];
pre[ti][tj][k][0]=ni;
pre[ti][tj][k][1]=nj;
pre[ti][tj][k][2]=k;
if (!inq[ti][tj])
{
qi.push(ti);
qj.push(tj);
inq[ti][tj]=1;
}
}
}
}
}
F(i,1,n) F(j,1,m)
{
if (!a[i][j])
{
printf("%d\n",dp[i][j][(1<<cnt)-1]);
dfs(i,j,(1<<cnt)-1);
out();
return 0;
}
}
}
BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树的更多相关文章
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- Luogu 4294 [WC2008]游览计划 | 斯坦纳树
题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...
- bzoj2595: [Wc2008]游览计划 斯坦纳树
斯坦纳树是在一个图中选取某些特定点使其联通(可以选取额外的点),要求花费最小,最小生成树是斯坦纳树的一种特殊情况 我们用dp[i][j]来表示以i为根,和j状态是否和i联通,那么有 转移方程: dp[ ...
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- BZOJ2595: [Wc2008]游览计划(斯坦纳树,状压DP)
Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 2030 Solved: 986[Submit][Status][ ...
- P4294 [WC2008]游览计划 (斯坦纳树)
题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...
- 洛谷4294 [WC2008]游览计划——斯坦纳树
题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...
- 【BZOJ-2595】游览计划 斯坦纳树
2595: [Wc2008]游览计划 Time Limit: 10 Sec Memory Limit: 256 MBSec Special JudgeSubmit: 1518 Solved: 7 ...
- bzoj 2595 [Wc2008]游览计划(斯坦纳树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2595 [题意] 给定N*M的长方形,选最少权值和的格子使得要求的K个点连通. [科普] ...
随机推荐
- css水平垂直居中的几个方法和技巧/居中之美
水平居中设置-行内元素 我们在实际工作中常会遇到需要设置水平居中场景,今天我们就来看看怎么设置水平居中的. 如果被设置元素为文本.图片等行内元素时,水平居中是通过给父元素设置 text-ali ...
- Entity Framework插入数据报错:Validation failed for one or more entities
www.111cn.net 编辑:lanve 来源:转载 今天在处理Entity Framework插入数据库时,报错: Validation failed for one or more entit ...
- AC自动机讲解+[HDU2222]:Keywords Search(AC自动机)
首先,有这样一道题: 给你一个单词W和一个文章T,问W在T中出现了几次(原题见POJ3461). OK,so easy~ HASH or KMP 轻松解决. 那么还有一道例题: 给定n个长度不超过50 ...
- ES6新数据类型map与set
一.map,简单的键值对映射,具有很快的查找速度 1. 初始化map,map的键名可以使用其他数据类型,对象的属性名只能使用字符串或symbol 使用二维数组 var m = new Map([['n ...
- Leetcode 7 反转整数Reverse Integer
给定一个 32 位有符号整数,将整数中的数字进行反转. 示例 1: 输入: 123 输出: 321 示例 2: 输入: -123 输出: -321 示例 3: 输入: 120 输出: 21 注意: ...
- STM32L0开发——ADC多通道采集,IDE和IAR开发注意事项
keil开发L0系列是免费的,官方提供许可的.因此建议Keil开发,L011F3由于flash只有8K,因此不建议HAL库,建议使用cubemx+LL(或snippets库).0.起初,可以参考官方库 ...
- Java实现——Socket网络通信的机制以及实现举例
1. 网络间的进程通信与Socket TCP/IP协议族中网络层的IP地址可以唯一标识网络中的主机,而传输层的协议+端口可以唯一标识主机中的应用程序(进程).这样利用这三元组就可以标识网络的进程了,网 ...
- Experimental considerations
先知 重金属颗粒与气孔大小 气孔位置.密度与开合时间 角质层厚度 意外 叶子第二天掉落 样本没有放冰箱 高光谱仪器损坏 天气下雨/雪 仪器预约 楼顶/实验室门卡提前一天预约 光合仪提前一天预约 ASD ...
- 电子邮件中的to、cc、bcc
电子邮件中的to.cc(carbon copy)和bcc(blind carbon copy),分别是收件人.抄送.密送 to 收件人 你想要给其发邮件的人 cc 抄送人 cc和to是一样的,但是cc ...
- Knockout v3.4.0 中文版教程-3-监控-通过监控创建视图模型(下)
6. 显式订阅监控 你通常不需要手动设置订阅,所以初学者应该跳过这一节. 对于高级用户,如果你想注册自己的订阅来监控通知变化,你可以使用 subscribe函数,比如: myViewModel.per ...