历届试题 区间移位

问题描述
  数轴上有n个闭区间D1,…,Dn。其中区间Di用一对整数[ai, bi]来描述,满足ai < bi。已知这些区间的长度之和至少有10000。所以,通过适当的移动这些区间,你总可以使得他们的“并”覆盖[0, 10000]——也就是说[0, 10000]这个区间内的每一个点都落于至少一个区间内。
  你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。
  具体来说,假设你将Di移动到[ai+ci, bi+ci]这个位置。你希望使得maxi |ci|  最小。
输入格式
  输入的第一行包含一个整数n,表示区间的数量。
  接下来有n行,每行2个整数ai,  bi,以一个空格分开,表示区间[ai, bi]。保证区间的长度之和至少是10000。
输出格式
  输出一个数,表示答案。如果答案是整数,只输出整数部分。如果答案不是整数,输出时四舍五入保留一位小数。
样例输入
2
10 5010
4980 9980
样例输出
20
样例说明
  第一个区间往左移动10;第二个区间往右移动20。
样例输入
4
0 4000
3000 5000
5001 8000
7000 10000
样例输出
0.5
样例说明
  第2个区间往右移0.5;第3个区间往左移0.5即可。
数据规模和约定
  对于30%的评测用例,1 ≤ n ≤ 10;
  对于100%的评测用例,1 ≤ n ≤ 10000,0 ≤ ai < bi  ≤ 10000。

//这里要确定的一件事是小数点最小的就是0.5,因为将1分为两部分肯定有一部分的小数大于0.5!!! 
//这里要乘2倍,不然无法出现小数点 
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int N;
struct node
{
	int left;
	int right;
};
vector<node> reg;
bool cmp(node x,node y)
{
	return x.right<y.right;
}

bool check(int x) //核心函数 
{
	int k = 0; //这里表示的是能覆盖的右边的极值点
	vector<node> tmp(reg); //这里相当于复制一个与reg一摸一样的向量 
	while(1)
	{
	int Found=0; //表示查找是否有覆盖
	for(int i = 0;i<tmp.size();i++)
	{
		node now = tmp[i];
		int ta = now.left;
		int tb = now.right;
		if(ta-x<=k&&tb+x>=k)
		{
			Found = 1;
			int len = tb-ta;
			if(ta+x>=k) k+=len;   //这里是覆盖的核心代码 
			else k=tb+x;       
			tmp.erase(tmp.begin()+i); //删除已经覆盖的区间
			break;  
		}
	}
	if(!Found||k>=20000) break;
	} 
	return k>=20000;
}
int main()
{
	scanf("%d",&N);
	int x,y;
	for(int i = 1;i<=N;i++)
	{
		node t;
		scanf("%d %d",&x,&y);
		x<<=1;
		y<<=1;
		t.left =x;
		t.right =y;
		reg.push_back(t);
	}
	sort(reg.begin(),reg.end(),cmp); //从左往右查找则需要右结点进行排列 
	int l=0,r=20000,mid;
	double ans=0; //可能不移动 
	while(l<=r) //注意二分条件包含等于 
	{
	 mid = (l+r)/2;
	 if(check(mid)) //mid 可以通过 
	 {
	 	r = mid-1;
	 	ans = mid;
	 }
	 else
	 {
	 	l = mid+1;
	 }
	}
	ans/=2.0;
	cout<<ans<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值