hiho216 Gas Stations

版权声明:转载我的原创博客情注明出处 https://blog.csdn.net/qq_31964727/article/details/82343969

目录

hiho216 Gas Stations

题意分析:

1.题是什么?

2.思路

(1).二分查值

(2).大根堆贪心


hiho216 Gas Stations

题目1 : Gas Stations

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

There are N gas stations on a straight, M kilo-meters long highway. The i-th gas station is Ai kilo-meters away from the beginning of the highway. (It is guaruanteed that there is one gas station at each end of the highway)

Now the mayor can build K more gas stations. He wants to minimize the maximum distance between two adjacent gas station. Can you help him?

输入

The first line contains 3 integer N, M, k. (2 <= N <= 1000, 1 <= M, K <= 100000)  

The second line contains N integer, A1, A2, ... AN. (0 = A1 <= A2 <= ... <= AN = M)

输出

The minimized maximum distance rounded to one decimal place.

样例输入

3 10 2  
0 2 10

样例输出

2.7

题意分析:

1.题是什么?

    现在有在长为m的路上有n个一直位置的加油站,并且起点终点肯定各有一个,现在你可以另外新建k个加油站,已任何两个加油站之间的最大距离最小化的方案为最优方案,问你这个最小化的最大距离是多少.

2.思路

(1).二分查值

    最小化的最大距离,最小化最大值!够明显了吧,二分查值的标志,这里取l=0,r=100*道路长度,我们查的是满足对这n-1个段切最多k刀就可以使每个切完后的段小于等于x/(float)100的最大的x,x就在0到100*道路长度之间,之所以是在100*道路长度之间取是因为答案要求保留小数点后1位,这样涉及到小数点后两位.

ac代码(这个做法的代码还未ac,正在努力,下面的错误代码仅供参考)

#include <stdio.h>
const int maxn=1001;
const int maxa=100005;
int n,m,k;
int a[maxn];
int dis[maxn];
bool c(int t){
	int num=0;
	for(int i=0;i<n-1;i++) num+=(dis[i]*100-1)/t; 
	return num<=k;
}
void solve(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	for(int i=0;i<n-1;i++) dis[i]=a[i+1]-a[i];
	
	int l=0,r=100*maxa,mid;
	for(int i=0;i<1000;i++){
		mid=(l+r)/2;
		if(c(mid)) r=mid; 
		else l=mid;
	}
	if(r%10>=5){//手动四舍五入 
		r=r-r%10;
		r+=10;
	}
	printf("%.1f",r*0.01);
}
int main(){
	solve();
	return 0;
}

(2).大根堆贪心

    这里涉及到一个稀疏度的概念,什么是稀疏度呢:

    稀疏度的概念是对于原本的那n-1个段,就像样例输入

3 10 2 

0 2 10 

    有两个段长度分别为2和8是吧,此时稀疏度就是2和8,我发现8最大,故而砍第二个段一刀,稀疏度变为2和4,4还是大,故而第二刀还是砍它,砍了之后稀疏度变为2和2.7,具体实现时可以用pair作为单位的大根堆来实现,first为稀疏度,second为原始段序号,这样甚至不用重载比较规则,因为pair为单位时默认以first排序,最重要的就是要另外开一个数组length记录原始段长,再开一个num记录一下这n-1个段每个段现在是被砍成了几段,初值自然都该是1,

    之后通过出大根堆根节点,就能知道哪个段稀疏度最高,最高的是第i个段就砍他,新的稀疏度就是 length[i]/(float)(num[i]+1),将之重新压进大根堆,这样重复砍k刀.

ac代码

#include <iostream>
#include <iomanip>
#include <queue>
using namespace std;
typedef pair<float,int> pa;
const int maxn=1001;
const int maxa=100005;
int n,m,k;
int a[maxn];       //记录加气站位置 
int length[maxn];//记录原始段长
int num[maxn];   //记录每个段现在是被切成了几段 

void solve(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n-1;i++){
		length[i]=a[i+1]-a[i];
		num[i]=1;
	}
	priority_queue<pa> que;
	for(int i=1;i<=n-1;i++) que.push(make_pair(length[i],i));
	for(int i=0;i<k;i++){
		int temp=que.top().second; //该砍哪一段,这是序号也是下标 
		que.pop();
		que.push(make_pair(length[temp]/(float)(num[temp]+1),temp));//切x刀是分为x+1段,这是第一个+1,第二个+1是刚刚切的这一刀 
		num[temp]++;
	}
	cout<<fixed<<setprecision(1);
	cout<<que.top().first<<endl;
	cout.unsetf(ios::fixed);
	cout.precision(6);
}
int main(){
	solve();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_31964727/article/details/82343969
gas