BZOJ2595 WC2008游览计划(斯坦纳树)
斯坦纳树板子题。
考虑状压dp,设f[i][j][S]表示当前在点(i,j)考虑转移,其所在的联通块包含的关键点集(至少)为S的答案。
转移时首先枚举子集,有f[i][j][S]=min{f[i][j][x]+f[i][j][y]-a[i][j]} (x&y=0,x|y=S)。
然后考虑从点(i,j)从哪拓展而来,有f[i][j][S]=min{f[x][y][S]}+a[i][j],其中(x,y)为(i,j)的相邻点,使用spfa转移。
这里第二种转移仅在相同关键点集下进行,因为由更小点集转移而来的情况已在第一种转移中被考虑。
对于输出方案,记录如何转移而来即可。
其实并没有搞懂。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 12
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,s,a[N][N],id[N][N],f[N][N][<<N],from[N][N][<<N][],q[N*N*N*N][];
int wx[]={,,,-},wy[]={,,-,};
bool flag[N][N];
char b[N][N];
void inc(int &x){x++;if (x>n*m+) x-=n*m+;}
void spfa(int k)
{
int head=,tail=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
tail++,q[tail][]=i,q[tail][]=j,flag[i][j]=;
do
{
inc(head);int x=q[head][],y=q[head][];flag[x][y]=;
for (int i=;i<;i++)
{
int u=x+wx[i],v=y+wy[i];
if (u&&u<=n&&v&&v<=m&&f[x][y][k]+a[u][v]<f[u][v][k])
{
f[u][v][k]=f[x][y][k]+a[u][v];
from[u][v][k][]=x,from[u][v][k][]=y;
if (!flag[u][v]) flag[u][v]=,inc(tail),q[tail][]=u,q[tail][]=v;
}
}
}while (head!=tail);
}
void getans(int x,int y,int k)
{
b[x][y]='o';
while (from[x][y][k][]>)
{
int u=from[x][y][k][],v=from[x][y][k][];
b[x=u][y=v]='o';
}
if (from[x][y][k][]<) getans(x,y,-from[x][y][k][]),getans(x,y,-from[x][y][k][]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj2595.in","r",stdin);
freopen("bzoj2595.out","w",stdout);
#endif
n=read(),m=read();
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
a[i][j]=read(),s+=(a[i][j]==);
if (!a[i][j]) id[i][j]=s;
}
memset(f,,sizeof(f));
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
{
f[i][j][]=a[i][j];
if (id[i][j]) f[i][j][<<id[i][j]-]=a[i][j];
}
for (int k=;k<(<<s);k++)
{
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
for (int x=k;x>=(k^x);x=x-&k)
if (f[i][j][x]+f[i][j][k^x]-a[i][j]<f[i][j][k])
{
f[i][j][k]=f[i][j][x]+f[i][j][k^x]-a[i][j];
from[i][j][k][]=-x,from[i][j][k][]=-(k^x);
}
spfa(k);
}
int ans=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
ans=min(ans,f[i][j][(<<s)-]);
cout<<ans<<endl;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
b[i][j]='_';
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (f[i][j][(<<s)-]==ans)
{
getans(i,j,(<<s)-);
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (!a[i][j]) b[i][j]='x';
for (int i=;i<=n;i++)
{
for (int j=;j<=m;j++)
putchar(b[i][j]);
cout<<endl;
}
return ;
}
}
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][ ...
- 【BZOJ2595】[Wc2008]游览计划 斯坦纳树
[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为 ...
- 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, 则该方块为一个 ...
随机推荐
- Android学习之AndroidStudio新建工程报Open File报错处理
在AndroidStudio中新建一个工程,报如下错误: 错误处理: 1.找到build.grandle(Module:app) 2.打开build.gradle(Module:app)文件如下图所示 ...
- NPOI DataTable导出excel
/// <summary> /// DataTable导出到Excel文件 /// </summary> /// <param name="dtSource&q ...
- SpringSecurity初步理解
Authenticating a User with LDAP 首先创建一个简单的web控制器 package hello; import org.springframework.web.bind.a ...
- Luogu3164 CQOI2014 和谐矩阵 异或高斯消元
传送门 题意:给出$N,M$,试构造一个$N \times M$的非全$0$矩阵,其中所有格子都满足:它和它上下左右四个格子的权值之和为偶数.$N , M \leq 40$ 可以依据题目中的条件列出有 ...
- 字符串阵列String[]转换为整型阵列Int[]
原始数据: string input = "3,7,2,8,1,9,1,34,67,78,22"; 要处理为: " }; 最终处理为: , , , , , , , , , ...
- Ionic Contoller类与Service类分开需要注意的问题
看了别人的项目把Controller类和Service类都写在了app.js文件里面,这不符合我的风格,想把他们分开成单独的文件,确遇见以下错误提示: ionic.bundle.min.js:133 ...
- RabbmitMQ-组成及简单使用
什么是MQ? MQ全程Message Queue,消息队列(MQ)是一种应用程序对应用程序的通信方法.MQ是消费者-生产者模型的典型代表.一端往消息队列中不断写消息而另一端则可以读取队列中的消息. R ...
- GATT服务搜索流程(一)
GATT的规范阅读起来还是比较简答, 但是这样的规范在代码上是如何实现的呢?下面就分析一下bluedroid 协议栈关于GATT的代码流程. BLE的设备都是在SMP之后进行ATT的流程的交互.从代码 ...
- InnoDB 文件系统
1. 操作系统文件系统inode 2. InnoDB的存储结构 2.1Innodb inode page 参考 http://mysql.taobao.org/monthly/2016/02/01/ ...
- Flutter - TabBar导航栏切换后,状态丢失
上一篇讲到了 Flutter - BottomNavigationBar底部导航栏切换后,状态丢失 里面提到了TabBar,这儿专门再写一下吧,具体怎么操作,来不让TabBar的状态丢失.毕竟大家99 ...