【二分答案】【Heap-Dijkstra】bzoj2709 [Violet 1]迷宫花园

显然最短路长度随着v的变化是单调的,于是可以二分答案,据说spfa在网格图上表现较差。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef double db;
typedef long long ll;
#define N 101
#define INF 2147483647.0
#define EPS 0.0000001
struct Point{db d;int u;};
bool operator < (Point a,Point b){return a.d>b.d;}
priority_queue<Point>q;
int T,n,m;
db L;
char a[N][N];
int en,v[N*N*4],first[N*N],next[N*N*4];
db w[N*N*4];
void AddEdge(int U,int V,db W)
{
	v[++en]=V;
	w[en]=W;
	next[en]=first[U];
	first[U]=en;
}
db d[N*N];
bool vis[N*N];
void dijkstra(int S)
{
	for(int i=1;i<=n*m;++i) d[i]=INF;
	d[S]=0; q.push((Point){0.0,S});
	while(!q.empty())
	  {
	  	Point x=q.top(); q.pop();
	  	if(!vis[x.u])
	  	  {
	  	  	vis[x.u]=1;
	  	  	for(int i=first[x.u];i;i=next[i])
	  	  	  if(d[v[i]]>d[x.u]+w[i])
	  	  	    {
	  	  	      d[v[i]]=d[x.u]+w[i];
	  	  	      q.push((Point){d[v[i]],v[i]});
	  	  	    }
	  	  }
	  }
}
int id[N][N],Sta,End;
const int dx[]={0,0,-1,1},dy[]={-1,1,0,0};
bool check(db x)
{
	en=0;
	memset(first,0,sizeof(int)*(n*m+1));
	memset(vis,0,sizeof(bool)*(n*m+1));
	for(int i=1;i<=n;++i)
	  for(int j=1;j<=m;++j) if(a[i][j]!=‘#‘)
	    {
	      for(int k=0;k<2;++k)
	        if(i+dx[k]>0&&i+dx[k]<=n&&j+dy[k]>0&&j+dy[k]<=m&&a[i+dx[k]][j+dy[k]]!=‘#‘)
	          AddEdge(id[i][j],id[i+dx[k]][j+dy[k]],1.0);
	      for(int k=2;k<4;++k)
	        if(i+dx[k]>0&&i+dx[k]<=n&&j+dy[k]>0&&j+dy[k]<=m&&a[i+dx[k]][j+dy[k]]!=‘#‘)
	          AddEdge(id[i][j],id[i+dx[k]][j+dy[k]],x);
	    }
	dijkstra(Sta);
	return L-d[End]<EPS;
}
int main()
{
	scanf("%d",&T);
	for(;T;--T)
	  {
	  	scanf("%lf%d%d\n",&L,&n,&m);
	  	en=0;
	  	for(int i=1;i<=n;++i)
	  	  gets(a[i]+1);
	  	for(int i=1;i<=n;++i)
	  	  for(int j=1;j<=m;++j)
	  	    {
	  	      id[i][j]=++en;
	  	      if(a[i][j]==‘S‘) Sta=id[i][j];
	  	      else if(a[i][j]==‘E‘) End=id[i][j];
	  	    }
	  	db l=0.0,r=10.0;
	  	while(r-l>EPS)
	  	  {
	  	  	db mid=(l+r)/2.0;
	  	  	if(check(mid)) r=mid;
	  	  	else l=mid+EPS;
	  	  }
	  	printf("%.5lf\n",l);
	  }
	return 0;
}
时间: 2024-10-09 08:36:01

【二分答案】【Heap-Dijkstra】bzoj2709 [Violet 1]迷宫花园的相关文章

二分+最短路判定 BZOJ 2709: [Violet 1]迷宫花园

BZOJ 2709: [Violet 1]迷宫花园 Sample Input 5 10.28 9 9 ######### # # # # # # # #S# # ##### # # ## # # # ### ### ##E # ######### 4.67 9 9 ######### # ## ## ### #S# # # # E ## # # ##### # ## ### # ##### # # # # ######### 39.06 9 9 ######### # # # # # # # #

{POJ}{3897}{Maze Stretching}{二分答案+BFS}

题意:给定迷宫,可以更改高度比,问如何使最短路等于输入数据. 思路:由于是单调的,可以用二分答案,然后BFS验证.这里用优先队列,每次压入也要进行检查(dis大小)防止数据过多,A*也可以.好久不写图论,WA成狗 #include <iostream> #include <string> #include <cstring> #include <cstdio> #include <algorithm> #include <memory>

505. 城市(二分答案)

505. 城市 ★★   输入文件:cost.in   输出文件:cost.out   简单对比时间限制:1 s   内存限制:128 MB [题目描述]在某个遥远的国家里,有n个城市.编号为1,2,3,……,n.这个国家的政府修建了m条双向的公路.每条公路连接着两个城市.沿着某条公路,开车从一个城市到另一个城市,需要花费一定的汽油.开车每经过一个城市,都会被收取一定的费用(包括起点和终点城市).所有的收费站都在城市中,在城市间的公路上没有任何的收费站.小红现在要开车从城市u到城市v(1<=u,

Codeforces 505E Mr. Kitayuta vs. Bamboos (贪心,二分答案,堆)

题目传送门 题意 有\(n\)根竹子,竹子\(i\)初始高度为\(h_i\),每天晚上会长高\(a_i\). 每天白天,你可以选择\(k\)根竹子(同一根竹子在同一个白天可以多次选择),把他们的高度减少\(p\),若竹子当前高度\(-p\)后\(<0\),则竹子高度变为\(0\). 最小化\(m\)天后最高的竹子的高度. 题解 首先最小化最大的...这种问题,显然可以用二分答案. 二分\(m\)天后最高的竹子的高度\(H\),然后问题就变成了判定性问题:是否存在一种方案,使得\(m\)天后竹子高

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

HDU3081Marriage Match II(二分答案+并查集+最大流SAP)经典

Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2507    Accepted Submission(s): 856 Problem Description Presumably, you all have known the question of stable marriage match. A

Codeforce 371C Hamburgers (二分答案)

题目链接 Hamburgers 二分答案,贪心判断即可. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define LL long long 7 8 char str[1010]; 9 LL len; 10 LL b, c, s, nb, nc, ns, pb, pc, ps; 11 LL money; 12 13 bool

POJ 3080 Blue Jeans(后缀数组+二分答案)

[题目链接] http://poj.org/problem?id=3080 [题目大意] 求k个串的最长公共子串,如果存在多个则输出字典序最小,如果长度小于3则判断查找失败. [题解] 将所有字符串通过拼接符拼成一个串,做一遍后缀数组,二分答案,对于二分所得值,将h数组大于这个值的相邻元素分为一组,判断组内元素是否覆盖全字典,是则答案成立,对于答案扫描sa,输出第一个扫描到的子串即可. [代码] #include <cstdio> #include <cstring> #inclu

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]