洛谷p1783海滩防御分析+题解代码

niiick niiick     2022-10-16     642

关键词:

洛谷P1783 海滩防御 分析+题解代码


题目描述:

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.

【样例解释】

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


算法分析:

复杂度可能不算很佳
但思路绝对简单

这里我们可以借鉴一下最小生成树的思想
即将整个图的所有边存于一个数组中(此步骤可以在输入防御塔坐标时完成)
此时图中只有节点而无边
将所有边按长度从小到大排序
然后依次加入这些边
每加入一条边就dfs遍历整个图
若此时图中某个联通块可以遍历到左右边界
此时的边权即为所求答案

还有几点需要注意的是

  • 由于所求的是最小半径,所以计算边权的时候要将两点间距离除以二作为边权
  • 海滩的列数编号为0~n,而0与n不能通行,所以左右边界为1与n-1

接下来献上蒟蒻的代码

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;

const int maxn=1000010;
typedef double dd;
int n,m;

struct node
{
    dd x;
    dd y;
}pt[maxn];

struct edge
{
    int u;
    int v;
    dd dis;
}E[1000010];

bool vis[maxn];
bool lft,rht;//判断是否联通左右边界 
vector<int> map[maxn]; 


dd dist(node a,node b)
{
    dd tx=fabs(a.x-b.x);
    dd ty=fabs(a.y-b.y);
    tx*=tx;
    ty*=ty;
    return sqrt(tx+ty);
}

void dfs(int u,dd dis)
{
    vis[u]=true;
    
    //若到达左/右边界则记录 
    if(pt[u].y+dis>=n-1) 
    rht=true;
    
    if(pt[u].y-dis<=1)
    lft=true;
    
    for(int j=0;j<map[u].size();j++)
    {
        int v=map[u][j];
        
        if(vis[v]==false)
        dfs(v,dis);
    }
}

bool cmp(edge a,edge b)
{
    return a.dis<b.dis;
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>pt[i].y>>pt[i].x;
        for(int j=1;j<i;j++)//在这里建边 
        {
            E[++cont].u=i;
            E[cont].v=j;
            E[cont].dis=dist(pt[i],pt[j])/2.0;
            //记得边权=两点距离/2.0 
        }
    }
    
    sort(E+1,E+1+cont,cmp);
     
    for(int i=1;i<=cont;i++)//从小到大加入每条边 
    {
        map[E[i].u].push_back(E[i].v);
        map[E[i].v].push_back(E[i].u);
        
        for(int j=1;j<=m;j++)
        {
            if(vis[j]==false)
            dfs(j,E[i].dis);
                
            if(lft&&rht)//若联通则直接输出并退出程序 
            {
                printf("%.2lf",E[i].dis);
                return 0;
            }
            
            else
            lft=rht=false;
            //注意判断封锁要在同一联通快内,所以每次都要重置 
        }
        memset(vis,false,sizeof(vis));
    }
    
    return 0;
}

其实我们在边的加入时还可以有优化
但是由于本蒟蒻比较懒
所以不想在优化了。。。。。。

洛谷p1854花店橱窗布置分析+题解代码

洛谷P1854花店橱窗布置分析+题解代码蒟蒻的第一道提高+/省选-,纪念一下。题目描述:某花店现有F束花,每一束花的品种都不一样,同时至少有同样数量的花瓶,被按顺序摆成一行,花瓶的位置是固定的,从左到右按1到V顺序编... 查看详情

洛谷p2832行路难分析+题解代码玄学最短路

洛谷P2832行路难分析+题解代码【玄学最短路】题目背景:小X来到了山区,领略山林之乐。在他乐以忘忧之时,他突然发现,开学迫在眉睫题目描述:山区有n座山。山之间有m条羊肠小道,每条连接两座山,只能单向通过,并会耗... 查看详情

洛谷p2194hxy烧情侣tarjan缩点分析+题解代码

洛谷P2194HXY烧情侣【Tarjan缩点】分析+题解代码题目描述:众所周知,HXY已经加入了FFF团。现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了。这里有n座电影院,n对情侣分别在每座电影院里,然后电影院里都有汽油... 查看详情

洛谷p1579哥德巴赫猜想(升级版)题解(代码片段)

洛谷P1579哥德巴赫猜想(升级版)题解这是本蒟蒻第一次发题解,望神犇们指正。原题如图现在先分析一下这道题,这道题数据强度不大只有20000,时间限制为1s,内存限制为125M。当然如果你想用一般的穷... 查看详情

题解洛谷p6413[coci2008-2009#3]najkraci(代码片段)

链接分析计算出最短路后,一条边是最短路的一部分,当且仅当起点的\\(f\\)值加上该边边权等于终点的\\(f\\)值,所以跑最短路后,对\\(m\\)条边进行判定,满足该条件的加入最短路图。加入后进行拓扑排序,计算以该边作为终点... 查看详情

洛谷3768:简单的数学题——题解(代码片段)

https://www.luogu.org/problemnew/show/P3768题面来自洛谷,因为没用markdown所以直接截的图。剩余的图是我用markdown写完然后截的图。参考洛谷第一篇题解。这个式子直观感受就需要莫比乌斯反演,大致的过程参考:BZOJ2693:jzptab那么跳过... 查看详情

题解洛谷p1975排序(代码片段)

分块,注意重复的值之间的处理。跟普通分块的操作一样的啦,具体可以参见‘不勤劳的图书管理员’。#include<bits/stdc++.h>usingnamespacestd;#definemaxn500000#definelowbit(i)i&(-i)#defineintlonglongintn,m,cnt,ans,B,c[200][maxn];structnodeintnu 查看详情

洛谷p1568赛跑题解(代码片段)

题目传送门这道题非常的水,只要你能搞清楚题意,将SH、KC不要混起来即可(所以我使用了结构体)#include<bits/stdc++.h>usingnamespacestd;intn,m,T,ans;intnow=-1;structnodeinta[1010],b[1010];intp;intN;SH,KC;intmain()scanf("%d%d",&n,&m 查看详情

洛谷p2676超级书架题解(代码片段)

题目传送门题目一看就是贪心。C++福利来了:sort。基本思路就是:要使奶牛最少那么肯定高的奶牛先啦。直接排序一遍(从高到矮)然后while,搞定!#include<bits/stdc++.h>#definelllonglongusingnamespacestd;llN,B,H[20010];boolcmp(intx,inty)retur... 查看详情

洛谷p2369exceededwarninga题解(代码片段)

题目传送门直接用sort排序最后输出即可。但是数组要使用shortint类型。否则会超内存。#include<bits/stdc++.h>usingnamespacestd;intn,m;shortinta[1000010];intmain()scanf("%d%d",&n,&m);for(inti=1;i<=n;i++)scanf("%d",&a[i] 查看详情

洛谷p2036perket题解(代码片段)

题目传送门这道题可以使用dfs深搜实现,在每次递归深搜时要更新ans。#include<bits/stdc++.h>usingnamespacestd;intn,ans=2147483647,s=1,b;boolflag[15];structnodeints,b;a[15];voiddfs(intk)if(k==n)ans=min(ans,abs(s-b));for(inti=1 查看详情

洛谷p2708硬币翻转题解(代码片段)

题目传送门真如题面所说,难度系数:☆☆☆☆☆(如果你看懂了)。从后往前扫一次,如果a[i]==0&&a[i-1]==1那么将ans+2。注意最后不要忘记开头if(a[0]==‘0‘)ans++;#include<bits/stdc++.h>usingnamespacestd;chara[300];intans;intmain()cin>... 查看详情

洛谷p1469找筷子题解(代码片段)

题目传送门先排序一遍,再一个一个判断是否有偶数个。注意for循环要i+=2。#include<bits/stdc++.h>usingnamespacestd;intn,a[10000010];intmain()scanf("%d",&n);for(inti=1;i<=n;i++)scanf("%d",&a[i]);sort(a+1,a+n+1);for(inti 查看详情

洛谷4238:模板多项式求逆——题解(代码片段)

https://www.luogu.org/problemnew/show/P4238如题所示,对998244353取模。板子没啥好说的。讲解看这位大佬:http://blog.miskcoo.com/2015/05/polynomial-inverse#include<cstdio>#include<cctype>#include<cstring>#inclu 查看详情

洛谷p1957口算练习题题解(代码片段)

题目传送门这道题是考字符串处理,另外输入要使用c++的cin的神奇功能。#include<bits/stdc++.h>usingnamespacestd;intn;charch;inta,b;chark;stringINTtoSTRING(intx)ostringstreamoss;oss<<x;returnoss.str();intmain()scanf("%d", 查看详情

洛谷2765:[网络流24题]魔术球问题——题解(代码片段)

...放多少个球。例如,在4根柱子上最多可放11个球。参考:洛谷前两页题解。一种做法是贪心, 查看详情

洛谷p2077红绿灯题解(代码片段)

题目传送门这道题一秒一秒的扫描一定会超时,所以就用一种O(N)的算法。#include<bits/stdc++.h>usingnamespacestd;intn,m,a[100001],b[100001],c[100001],x=0,k;intmain()scanf("%d%d",&n,&m);for(inti=1;i<n;i++)scanf("%d",& 查看详情

洛谷p1579哥德巴赫猜想(升级版)题解(代码片段)

洛谷P1579哥德巴赫猜想(升级版)题解这是本蒟蒻第一次发题解,望神犇们指正。原题如图现在先分析一下这道题,这道题数据强度不大只有20000,时间限制为1s,内存限制为125M。当然如果你想用一般的穷... 查看详情