[2018.04.17][水][日志][8][#195][路由器安置][Wi-Fi][->][二分/递增][网速堪忧x1]

本文讨论了一道关于如何在给定街道上有效地布置WIFI路由器的题目,目标是找到覆盖所有居民所需的最小路由器半径。通过采用二分搜索策略,可以解决这个问题并减少成本。文章提供了样例数据和解题思路,包括如何进行二分枚举判断直径值的可行性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[背景]

    抓紧时间写完!

    今天耗费VHOS心力最多的是这道虚伪的题目,首先必须要吐槽一下:为什么WIFI设置这么坑!!!!

    好的,由于我们上的是分治,所以我优先选择了二分来做这道题,同时给出周神的递增版本。

[题目]

题目描述
一条街道安装WIFI,需要放置M个路由器。整条街道上一共有N户居民,分布在一条直线上,每一户居民必须被至少一台路由器覆盖到。现在的问题是所有路由器的覆盖半径是一样的,我们希望用覆盖半径尽可能小的路由器来完成任务,因为这样可以节省成本。
输入格式
输入文件第一行包含两个整数M和N,以下N行每行一个整数Hi表示该户居民在街道上相对于某个点的坐标。 
输出格式
输出文件仅包含一个数,表示最小的覆盖半径,保留一位小数。
样例数据
input
2 3
1
3
10
output
1.0
数据规模与约定
时间限制:1s
1s
空间限制:256MB
256MB
注释

对于60%的数据,有1 ≤ N, M ≤ 100,-1000 ≤ Hi ≤ 1000; 对于100%的数据,有1 ≤ N, M ≤ 100000,-10000000 ≤ Hi ≤ 10000000。

[二分的分析]

很显然这道题要枚举最合适的路由器范围直径(然后除以二出答案)

而枚举的任务就交给枚举的代码了;


以上是程序的准备模块


很好,二分的主体完成了,现在只要判断这个直径值成不成立就行了;

虚伪虚伪虚伪虚伪,严重怀疑网络稳定性


[code]

[二分]

#include<bits/stdc++.h>

const int maxn=1<<17;

int lc[maxn]={};
int home=0,max_wifi=0;

int ip(void)
{
	int sign=1,num=0;
	char c=getchar();
	for(;c<'0'||c>'9';c=getchar())
		 if(c=='-')
			sign=-1;
	for(;c>='0'&&c<='9';c=getchar())
		num=(num<<1)+(num<<3)+c-'0';
	return num*sign;
}

bool check(int size)
{
	int wifi=0;
	int left=1,right=1;
	
	while(right<=home)
	{
		while(lc[right]-lc[left]<=size&&right<=home)
			right++;
		
		left=right;
		wifi++;
	}
	
	if(wifi<=max_wifi)
		return true;
	else
		return false;
}

int main(void)
{
	max_wifi=ip();
	home=ip();
	
	for(int i=1;i<=home;i++)
	{
		lc[i]=ip();
	}
	std::sort(lc+1,lc+home+1);
	
	int left=-1<<22;
	int right=1<<22;
	int mid=0;
	while(left+1<right)
	{
		mid=(left+right)>>1;
		if(check(mid))
			right=mid;
		else
			left=mid;
	}
	
	if(check(left))
		printf("%.1f",left*1.0/2);
	else
		printf("%.1f",right*1.0/2);
	return 0;
}

[递增]

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cctype>

const int maxn=1<<17;

int lc[maxn]={};
int home=0,max_wifi=0;

inline int ip(void)
{
	register bool sign=false;
	register char ip='#';
	while(!isdigit(ip=getchar()))
		sign|=(ip=='-');
	
	register int op=(ip^'0');
	while(isdigit(ip=getchar()))
		op=(op<<3)+(op<<1)+(ip^'0');
	return sign?~op+1:op;
}

bool check(int size)
{
	int wifi=0;
	int left=1,right=1;
	
	while(right<=home)
	{
		while(lc[right]-lc[left]<=size&&right<=home)
			right++;
		
		left=right;
		wifi++;
	}
	
	return (wifi<=max_wifi);
}

int main(void)
{
	max_wifi=ip();
	home=ip();
	
	for(int i=1;i<=home;i++)
	{
		lc[i]=ip();
	}
	std::sort(lc+1,lc+home+1);
	
	int answer=lc[home]-lc[1];
	for (int i=log2(answer);i>=0;i--)
		answer-=(1<<i)*(answer-(1<<i)>0&&check(answer-(1<<i)));
	
	printf("%.1f",answer*1.0/2);
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值