zoukankan      html  css  js  c++  java
  • [题解]P1783 海滩防御

    Description

    链接Luogu

    题目描述

    WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭。于是,WLP动用了他那丰满且充实的大脑(或许更偏向前者),想出了一个好主意,他把海滩分成垂直于海岸线的若干列,在其中的几列上放置几个信号塔,试图来监视整个海滩。然而,WLP是一个非常心急的人,他把信号塔建好后才发现还需给信号塔供能,它们才能投入使用(这不是废话么),它们都有一个工作半径,一个圆形区域里的所有敌人都逃不过它们的监视,不过,WLP发现,敌人们非常狡猾,除非他将道路完全封死,否则WLP的敌人可以走过一条任意弯曲的路(不一定走整点,但是不会出第0列和第N列构成的边界)来偷他的东西。

    于是,WLP就思考了:到底需要给每个信号塔多大的工作半径,才能将从海滩到内地的路径完全封死呢?他再次动用了他那丰满且充实的大脑,想了一堂数学课,终于,还是没想出来。于是,他向LZZ神犇求助(额……C_SUNSHINE的身份是不是暴露了)。

    终于,在WLP:“%!*@#!*(*!*#@$^&(此处省略无数卖萌场景)”的哀求下,LZZ神犇写了一个程序,在1s内就解决了问题。但是,邪恶的LZZ神犇决定要将这个难题共享给无数无辜的OIer,所以,现在轮到你了。

    输入格式

    第一行两个整数N和M:表示海滩被WLP分成的列数0-N和信号塔个数。

    第2-M+1行:每行两个数Xi,Yi表示1-M号信号塔所在的列数和离开海滩的距离。

    输出格式

    一行一个实数,表示最小的工作半径,保留两位小数。

    输入输出样例

    输入 #1

    5 5
    1 5
    3 5
    5 5
    4 30
    2 15
    

    输出 #1

    1.00
    

    输入 #2

    100 2
    30 50
    90 100
    

    输出 #2

    39.05
    

    说明/提示

    对于10%的数据:1≤M≤10,1≤Yi≤100;
    对于30%的数据:1≤M≤50,1≤Yi≤1,000;
    对于80%的数据:1≤M≤500,1≤Yi≤1,000;
    对于100%的数据:1≤M≤800,1≤N≤1000,1≤Xi≤N,1≤Yi≤100,000.

    【样例解释】

    注意,封锁海滩是指,敌人的深入程度是有限制的,若敌人绕过了所有的信号塔,并且可以长驱直入,那么就说明道路没有完全封锁。

    题解

    这题的标签是并查集,看完题容易想到二分答案求解半径。
    于是我就向二分+并查集的方向想了好久,木有结果

    最后我的解法是最短路:
    每两个信号塔之间建一条边,边长使他们之间距离的一半。
    信号塔到边缘也要建边。
    然后就是最短路啦。

    Code:

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    #include <vector>
    #include <cstring>
    
    #define MAXN 805
    using namespace std;
    
    template<typename T> 
    T Aabs(T x) {
    	return x >= 0 ? x : -x;
    }
    
    template<typename T> 
    T sqr(T x) {
    	return x * x;
    }
    
    struct point {
    	int x, y;
    	point(int xi, int yi) {
    		x = xi;
    		y = yi;
    	}
    };
    
    struct node {
    	int x;
    	double w;
    	node(int xi, double wi) {
    		x = xi;
    		w = wi;
    	}
    };
    
    struct pri_v {
    	int x;
    	double w;
    	pri_v(int xi, double wi) {
    		x = xi;
    		w = wi;
    	}
    
    	bool operator < (const pri_v &a) const {
    		return this->w > a.w;
    	}
    };
    
    int n, m;
    vector<point> tower;
    vector<node> G[MAXN];
    bool vis[MAXN];
    double dis[MAXN];
    
    double calc(point x, point y) {
    	int xdis = Aabs(x.x - y.x);
    	int ydis = Aabs(x.y - y.y);
    	return sqrt(sqr(xdis) + sqr(ydis));
    }
    
    double dijstra(int n, int s, int t, int mx) {
    	priority_queue<pri_v> q;
    
    	for (int i = 0; i <= n; ++i) dis[i] = mx * mx;
    	memset(vis, 0, sizeof(vis));
    	dis[s] = 0;
    	q.push(pri_v(s, 0));
    
    	while (q.size()) {
    		int x = q.top().x;
    		q.pop();
    		
    		if (vis[x]) continue;
    		vis[x] = true;
    
    		for (unsigned i = 0; i < G[x].size(); ++i) {
    			int y = G[x][i].x;
    			double z = G[x][i].w;
    
    			if (dis[y] > max(dis[x], z)) { //注意这里和普通最短路不一样,这里的最短路不是路径长度总和,而是最长的那条边的边长。
    				dis[y] = max(dis[x], z);
    				q.push(pri_v(y, dis[y]));
    			}
    		}
    	}
    
    	return dis[t];
    }
    
    int main() {
    	scanf("%d %d", &n, &m);
    	for (int i = 1; i <= m; ++i) {
    		int x, y;
    		scanf("%d %d", &x, &y);
    		for (unsigned j = 0; j < tower.size(); ++j) {
    			G[i].push_back(node(j + 1, calc(tower[j], point(x, y)) / 2));
    			G[j + 1].push_back(node(i, calc(tower[j], point(x, y)) / 2));
    		}
    		tower.push_back(point(x, y));
    	}
    
    	for (unsigned j = 0; j < tower.size(); ++j) {
    		point nowt = tower[j];
    		G[m + 1].push_back(node(j + 1, nowt.x));
    		G[j + 1].push_back(node(m + 1, nowt.x));
    
    		G[m + 2].push_back(node(j + 1, n - nowt.x));
    		G[j + 1].push_back(node(m + 2, n - nowt.x));
    	}
    
    	double dist = dijstra(m + 2, m + 1, m + 2, n);
    	printf("%.02lf
    ", dist);
    	return 0;
    }
    
  • 相关阅读:
    HDU 2112 HDU Today,最短路径算法,Dijkstra
    最小生成树,POJ和HDU几道题目的解题报告(基于自己写的模板)
    图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)
    合并相同值得单元格(纵向)
    request.startAsync()不支持异步操作
    DIV强制不换行
    兼容各浏览器的css背景图片拉伸代码
    程序猿之八荣八耻
    使用JEECG过程中的问题汇总(持续更新)
    Firefox的缓存问题
  • 原文地址:https://www.cnblogs.com/szdytom/p/12491590.html
Copyright © 2011-2022 走看看