斯坦纳树板子题。

  考虑状压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游览计划(斯坦纳树)的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ2595】[Wc2008]游览计划 斯坦纳树

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

  5. Luogu 4294 [WC2008]游览计划 | 斯坦纳树

    题目链接 Luogu 4294 (我做这道题的时候BZOJ全站的SPJ都炸了 提交秒WA 幸好有洛谷) 题解 这道题是[斯坦纳树]的经典例题.斯坦纳树是这样一类问题:带边权无向图上有几个(一般约10个 ...

  6. 【BZOJ-2595】游览计划 斯坦纳树

    2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1518  Solved: 7 ...

  7. BZOJ 2595 [Wc2008]游览计划 ——斯坦纳树

    [题目分析] 斯坦纳树=子集DP+SPFA? 用来学习斯坦纳树的模板. 大概就是用二进制来表示树包含的点,然后用跟几点表示树的形态. 更新分为两种,一种是合并两个子集,一种是换根,换根用SPFA迭代即 ...

  8. P4294 [WC2008]游览计划 (斯坦纳树)

    题目链接 差不多是斯坦纳树裸题,不过边权化成了点权,这样在合并两棵子树时需要去掉根结点的权值,防止重复. 题目还要求输出解,只要在转移时记录下路径,然后dfs一遍就好了. #include<bi ...

  9. 洛谷4294 [WC2008]游览计划——斯坦纳树

    题目:https://www.luogu.org/problemnew/show/P4294 大概是状压.两种转移,一个是以同一个点为中心,S由自己的子集拼起来:一个是S相同.中心不同的同层转移. 注 ...

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

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

随机推荐

  1. 通过C# WinForm控件创建的WPF WIndow窗口控件无法输入的问题

    原文:通过WinForm控件创建的WPF 控件无法输入的问题 今天把写的一个WPF程序发布到别的机器上执行,发现一个比较奇怪的问题:在那个机器上用英文输入法无法输入数字,非要切换到中文输入法才行:但在 ...

  2. CSS3选择器之:nth-child(n)

    第一次用到这个选择器还是为了解决下面了的问题: 手机的前端,我们使用了mint-ui,里面有一个日期选择控件,但是选择的时候没有提供年月的选择器,如: 而是提供了下面的方式: 为了达到上面的效果,使用 ...

  3. Luogu P2257 YY的GCD

    莫比乌斯反演第一题.莫比乌斯反演入门 数论题不多BB,直接推导吧. 首先,发现题目所求\(ans=\sum_{i=1}^n\sum_{j=1}^m [\gcd(i,j)=prime]\) 考虑反演,我 ...

  4. Luogu P2059 [JLOI2013]卡牌游戏

    一道比较简单的概率DP 首先看到这种题目和数据范围,就要毫不犹豫地列DP方程: 我们令\(f_{i,j}\)表示还剩下i个人时编号为j的人的胜率,那么首先我们可以知道边界条件\(f_{1,1}=1\) ...

  5. (11)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- Thrift高效通讯 (完结)

    一. 什么是 RPC Restful 采用 Http 进行通讯,优点是开放.标准.简单.兼容性升级容易: 缺点是性能略低.在 QPS 高或者对响应时间要求苛刻的服务上,可以用 RPC(Remote P ...

  6. 记一次艰难的jquery easy-ui ajax post 体验

    分享的经验和教训是: 1.jquery easy-ui ajax post 复杂的Json给后端解析,后端如果接收和解析 2.asp.net webform jquery easy-ui datagr ...

  7. zookeeper Error contacting service 解决

    连接kafka集群,有一个kafka机器连接失败 到该kafka机器上查询kafka进程,发现没有, 再查看zookeeper状态,提示 Error contacting service. It is ...

  8. libc.so.6: version 'GLIBC_2.14' not found报错提示的解决方案

    线上一台服务器在执行leveldb程序的时候,报错:"libc.so.6: version `GLIBC_2.14' not found". 排查原因及解决方法如下: 1)产生原因 ...

  9. 《linux内核设计与实现》第四章

    调度程序负责决定哪个进程投入运行,何时运行以及运行多长时间.只有通过调度程序合理调度,系统资源才能最大限度发挥作用,多进程才会有并发执行的效果. 最大限度地利用处理器时间的原则是,只要有可以执行的进程 ...

  10. 跟踪分析Linux内核的启动过程

    潘俊洋 原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.准备 搭建环境 1 2 ...