【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=2595

【题意】

给定N*M的长方形,选最少权值和的格子使得要求的K个点连通。

【科普】

“斯坦纳树”就是包含给定点的最小生成树。

【思路】

  那么本题就是求一棵斯坦纳树。

设f[i][j][S]表示在点(i,j)且与之相连的点的状态为S。

有两种转移:

f[i][j][S]<-f[i][j][S’]+f[i][j][S-S’]-a[i][j],合并子集

f[i][j][S]<-f[i’][j’][S]+a[i][j],相邻点更新

第一种转移可能包含重点的情况,所以还需要第二种转移方程。

第一种转移可以直接枚举子集完成转移。

  第二种转移的更新虽然会出现环的情况,但结果一定满足三角形不等式

    f[i][j][S]<=f[i’][j’][S]  +a[i][j]

所以可以用spfa算法求。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; const int N = ;
const int inf = 0xf0f0f0f;
const int dx[]={,-,,};
const int dy[]={,,,-}; int n,m,K,st[N][N];
int vis[N][N],a[N][N],f[N][N][<<N],pre[N][N][<<N]; int pack(int i,int j) { return i*+j; }
void unpack(int x,int& i,int& j) { i=x/,j=x%; }
int pack2(int i,int j,int st) { return i*+j*+st; }
void unpack2(int x,int& i,int& j,int& st) { st=x%,i=x/,j=(x/)%; } int upd(int i,int j,int s,int x,int y,int s2,int w)
{
if(f[i][j][s]>w) return f[i][j][s]=w,pre[i][j][s]=pack2(x,y,s2),;
return ;
} queue<int> q;
int inq[N*N];
void spfa(int sta)
{
while(!q.empty()) {
int u=q.front(),i,j; q.pop();
inq[u]=;
unpack(u,i,j);
FOR(k,,) {
int x=i+dx[k],y=j+dy[k],tmp;
if(x<||x>=n||y<||y>=m) continue;
if(upd(x,y,sta,i,j,sta,f[i][j][sta]+a[x][y])&&(!inq[tmp=pack(x,y)])) {
q.push(tmp),inq[tmp]=;
}
}
}
}
void dfs(int i,int j,int st)
{
int x,y,nst;
vis[i][j]=;
if(!pre[i][j][st]) return ;
unpack2(pre[i][j][st],x,y,nst);
dfs(x,y,nst);
if(x==i&&y==j) dfs(x,y,st-nst);
} int main()
{
//freopen("trip.in","r",stdin);
//freopen("trip.out","w",stdout);
memset(f,0xf,sizeof(f));
scanf("%d%d",&n,&m);
FOR(i,,n-) FOR(j,,m-) {
scanf("%d",&a[i][j]);
if(!a[i][j]) st[i][j]=<<(K++),f[i][j][st[i][j]]=;
}
int all=(<<K),tmp;
FOR(sta,,all-) {
FOR(i,,n-) FOR(j,,m-) {
for(int s=sta&(sta-);s;s=(s-)&sta)
upd(i,j,sta,i,j,s,f[i][j][s]+f[i][j][sta-s]-a[i][j]);
if(f[i][j][sta]!=inf) q.push(tmp=pack(i,j)),inq[tmp]=;
}
spfa(sta);
}
FOR(i,,n-) FOR(j,,m-) if(!a[i][j]) {
printf("%d\n",f[i][j][all-]);
dfs(i,j,all-);
FOR(ii,,n-) {
FOR(jj,,m-) {
if(!a[ii][jj]) putchar('x');
else if(vis[ii][jj]) putchar('o');
else putchar('_');
}
puts("");
}
return ;
}
}

bzoj 2595 [Wc2008]游览计划(斯坦纳树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Python中itertools模块

    itertools模块包含创建有效迭代器的函数,可以用各种方式对数据进行循环操作,此模块中的所有函数返回的迭代器都可以与for循环语句以及其他包含迭代器(如生成器和生成器表达式)的函数联合使用. ch ...

  2. Arraysort

    import java.util.*;public class Arraysort{ public static void main(String[]args){ int[]a={100,34,88, ...

  3. KDE/QT与GNOME/GTK比较

    转自:http://linux.chinaunix.net/bbs/thread-1125240-1-1.html 虽然在商业方面存在竞争,GNOME与KDE两大阵营的开发者关系并没有变得更糟,相反他 ...

  4. 机器学习 —— 概率图模型(Homework: StructuredCPD)

    Week2的作业主要是关于概率图模型的构造,主要任务可以分为两个部分:1.构造CPD;2.构造Graph.对于有向图而言,在获得单个节点的CPD之后就可依据图对Combine CPD进行构造.在获得C ...

  5. 人脸识别必读的N篇文章

    一,人脸检测/跟踪 人脸检测/跟踪的目的是在图像/视频中找到各个人脸所在的位置和大小:对于跟踪而言,还需要确定帧间不同人脸间的对应关系. 1, Robust Real-time Object Dete ...

  6. (step4.3.4)hdu 1258(Sum It Up——DFS)

    题目大意:输入t,n,接下来有n个数组成的一个序列.输出总和为t的子序列 解题思路:DFS 代码如下(有详细的注释): #include <iostream> #include <a ...

  7. Mac + IDEA + JRebel破解方法.

    [重要提示]---最佳人生 一.只推荐当计算机无法访问互联网时使用本破解文件. 二.如果可以访问互联网,建议直接到JRebel官网注册JRebel会员获取[正版永久免费]使用的授权码.JRebel会员 ...

  8. java--面向接口编程

    之前看的一本书的笔记,上周再看设计模式的时候,想到了这篇之前在看某本书时候的笔记. 面向接口编程很重要的一点就是接口回调,用接口声明的变量称作接口变量,属于引用型变量,可以存放实现该接口的类的实例的引 ...

  9. OAuth2.0和SSO授权的区别

    OAuth2.0和SSO授权   一.OAuth2.0授权协议 一种安全的登陆协议,用户提交的账户密码不提交到本APP,而是提交到授权服务器,待服务器确认后,返回本APP一个访问令牌,本APP即可用该 ...

  10. ubuntu set host name

    http://wiki.joyent.com/wiki/display/jpc2/Setting+the+Host+Name+on+a+Linux+VM Set the host name in th ...