【BZOJ】【2595】【WC2008】游览计划

Orz zky神犇http://blog.csdn.net/iamzky/article/details/42029921

spfa的灵活应用!(好像是求了一个叫做斯坦纳树的东西……)

o(︶︿︶)o 唉我就是太水了,离散化写跪了,x*1e5+y*1e4+k,但是这题里我x和y的范围是[1,10]所以在y==10的时候会出错!!

  1 //BZOJ 2595
  2 #include<queue>
  3 #include<cmath>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<iostream>
  8 #include<algorithm>
  9 #define rep(i,n) for(int i=0;i<n;++i)
 10 #define F(i,j,n) for(int i=j;i<=n;++i)
 11 #define D(i,j,n) for(int i=j;i>=n;--i)
 12 using namespace std;
 13 const int N=13,INF=~0u>>2;
 14 const int fx[]={1,0,-1,0},
 15           fy[]={0,1,0,-1};
 16 typedef long long LL;
 17 //#define debug
 18 int n,m,a[N][N],d[N][N],cnt=0;
 19 int f[N][N][1100],pre[N][N][1100];
 20 bool vis[N][N];
 21
 22 struct node{ int x,y; };
 23 queue<node>Q;
 24 inline int pack(int x,int y,int s){
 25     return x*1000000+y*10000+s;
 26 }
 27
 28 void spfa(int Set){
 29     while(!Q.empty()){
 30         int x=Q.front().x,y=Q.front().y; Q.pop();
 31         vis[x][y]=0;
 32         rep(i,4){
 33             int tx=x+fx[i],ty=y+fy[i];
 34             if (tx<1 || ty<1 || tx>n || ty>m) continue;
 35
 36             if (f[tx][ty][Set]>f[x][y][Set]+a[tx][ty]){
 37                 f[tx][ty][Set]=f[x][y][Set]+a[tx][ty];
 38                 pre[tx][ty][Set]=pack(x,y,Set);
 39                 if (!vis[tx][ty]) Q.push((node){tx,ty}),vis[tx][ty]=1;
 40             }
 41         }
 42     }
 43 }
 44
 45 void dfs(int i,int j,int Set){
 46     if (pre[i][j][Set]==INF || pre[i][j][Set]%5000==0)return;
 47     vis[i][j]=1;
 48     int x=pre[i][j][Set]/1000000,
 49     y=(pre[i][j][Set]-x*1000000)/10000,
 50     z=(pre[i][j][Set]-x*1000000-y*10000);
 51     #ifdef debug
 52     printf("%d,%d,%d----->%d,%d,%d\n",x,y,z,i,j,Set);
 53     #endif
 54     dfs(x,y,z);
 55     if (x==i && y==j) dfs(i,j,Set-z);
 56 }
 57
 58 void solve(){
 59     for(int Set=1;Set<(1<<cnt);Set++){
 60         F(x,1,n) F(y,1,m){
 61             for(int s=Set&(Set-1);s;s=(s-1)&Set){
 62                 if(f[x][y][Set]>f[x][y][s]+f[x][y][Set-s]-a[x][y]){
 63                     f[x][y][Set]=f[x][y][s]+f[x][y][Set-s]-a[x][y];
 64                     pre[x][y][Set]=pack(x,y,s);
 65                 }
 66             }
 67             if (f[x][y][Set]!=INF){Q.push((node){x,y}); vis[x][y]=1;}
 68         }
 69         spfa(Set);
 70     }
 71     int x,y;
 72     F(i,1,n) F(j,1,m) if (!a[i][j]) {x=i; y=j;break;}
 73     printf("%d\n",f[x][y][(1<<cnt)-1]);
 74
 75     #ifdef debug
 76     F(i,1,n) F(j,1,m)
 77         F(k,0,(1<<cnt)-1)
 78             if (pre[i][j][k]!=INF)
 79             printf("pre[%d][%d][%d]=%d\n",i,j,k,pre[i][j][k]);
 80     #endif
 81     dfs(x,y,(1<<cnt)-1);
 82     F(i,1,n) F(j,1,m){
 83         if (!a[i][j]) putchar(‘x‘);
 84         else if(vis[i][j]) putchar(‘o‘);
 85         else putchar(‘_‘);
 86         if (j==m) puts("");
 87     }
 88 }
 89
 90 int main(){
 91     #ifndef ONLINE_JUDGE
 92     freopen("file.in","r",stdin);
 93 //    freopen("file.out","w",stdout);
 94     #endif
 95     scanf("%d%d",&n,&m);
 96     F(i,0,10) F(j,0,10)
 97         F(k,0,(1<<10)) f[i][j][k]=pre[i][j][k]=INF;
 98     F(i,1,n)
 99         F(j,1,m){
100             scanf("%d",&a[i][j]);
101             if (!a[i][j])
102                 f[i][j][1<<(cnt++)]=0;
103         }
104     solve();
105     return 0;
106 }

时间: 2024-10-12 03:50:37

【BZOJ】【2595】【WC2008】游览计划的相关文章

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

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

BZOJ 2595: [Wc2008]游览计划 [DP 状压 斯坦纳树 spfa]【学习笔记】

传送门 题意:略 论文 <SPFA算法的优化及应用> http://www.cnblogs.com/lazycal/p/bzoj-2595.html 本题的核心就是求斯坦纳树: Steiner Tree: Given an undirected graph with non-negative edge weights and a subset of vertices, usually referred to as terminals, the Steiner tree problem in g

BZOJ 2595 Wc2008 游览计划 斯坦纳树

题目大意:给定一个矩阵,有一些关键点,每个格子有权值,选择一些格子使所有关键点连通,求最小权值和 传说中的斯坦纳树- - 感觉不是很难理解的样子 枚举连通的状态,对于每个状态先对每个位置枚举子集进行合并,然后对这个状态的分层图进行SPFA 看了几分代码还是ZKY写的比较简洁- - 此外就是终于能通过操作符重载访问结构体里的三维数组了- - 我真是太丧病了233 #include <cstdio> #include <cstring> #include <iostream>

【BZOJ 2595】2595: [Wc2008]游览计划 (状压DP+spfa,斯坦纳树?)

2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 1572  Solved: 739 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数目. 相邻的整数用 (若干个) 空格隔开,行首行末也可能有多余的空格. Output 由 N

[Wc2008]游览计划

2595: [Wc2008]游览计划 Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge[Submit][Status][Discuss] Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数目. 相邻的整数用 (若干个) 空格隔开,行首行末也可能有多余的空格. Output 由 N

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

[BZOJ2595][Wc2008]游览计划 Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数目. 相邻的整数用 (若干个) 空格隔开,行首行末也可能有多余的空格. Output 由 N + 1行组成.第一行为一个整数,表示你所给出的方案中安排的志愿者总数目. 接下来 N行,每行M 个字符,描述方案中相应方块的情况: z  ‘_’(下划线)表示该

bzoj2595 [Wc2008]游览计划

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2595 [题解] 斯坦纳树模板题.学了一发斯坦纳树. 对于一般的斯坦纳树,是 给出一些点和一些关键点和边,要求选择权值和最小的连通块使得关键点连通. 那么一般我们用f(x,status)表示在x,状态为status的最小权值和. 本题我们采用f(i,j,status)表示在(i,j),状态为status的最小权值和. 一开始权值就是题目给的,如果是景点那么在对应的标号的status赋值即可.

BZOJ_2595_[Wc2008]游览计划_斯坦纳树

题意: 分析: 斯坦纳树裸题,有几个需要注意的地方 给出矩阵,不用自己建图,但枚举子集转移时会算两遍,需要减去当前点的权值 方案记录比较麻烦,两边的转移都需要记录,最后dfs找方案会比较容易理解 代码: #include <stdio.h> #include <string.h> #include <algorithm> #include <queue> using namespace std; #define N 110 #define LL long l

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

Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special JudgeSubmit: 2030  Solved: 986[Submit][Status][Discuss] Description Input 第一行有两个整数,N和 M,描述方块的数目. 接下来 N行, 每行有 M 个非负整数, 如果该整数为 0, 则该方块为一个景点:否则表示控制该方块至少需要的志愿者数目. 相邻的整数用 (若干个) 空格隔开,行首行末也可能有多余的空格. Outpu

[WC2008]游览计划 「斯坦那树模板」

斯坦那树 百度释义 斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种.最小生成树是在给定的点集和边中寻求最短网络使所有点连通.而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小. 即最小斯坦那树即为并非选择所有的结点,而是选择一部分结点,为保证它们连通,且求解最小开销 题解 斯坦那树模板 发现直接表示点的存在性没有意义 设函数 \(f[i][state]\) 表示:对于点 \(i\),其它结点与其连通情况 那么有两种转移 其一.由其子集转移 \[f[i][state