题目 1846: 蓝桥杯2017年第八届真题-区间移位
这个题和扫地机器人很像。
check很像,其他的不像。
扫地机器人的步数和扫描范围需要自己找规律,区间移位要按右区间升序排序,要先乘2来avert小数0.5
check都是需要一个左端点L,左端点的是已经弄完结束了的
但是左端点的更新也要自己找规律,扫地机器人是根据当前遍历到的机器人的位置和左端点L的位置的前后不同更新L,区间移位是根据L和当前遍历到的区间最大能移到L的左边还是右边,以及区间右端点来看的。
总之很难。
讲的很好的一片题解
传送门
关于为什么是按照右端点排序:
摘自传送门
但是我认为这里最后更新的是3000不是两千三。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e4+10;
const int maxn = 2*1e4;
int n;
struct node{
int l,r;
};
vector<node>reg;
bool cmp(node x,node y)
{
return x.r<y.r;
}
bool check(int x)
{
int L=0;
vector<node>tmp(reg);
while(true)
{
bool find=false; //表示找到一个能接上的区间
for(int i=0;i<tmp.size();i++)
{
int ta=tmp[i].l,tb=tmp[i].r;
cout<<ta<<" "<<tb<<endl;
int len=tb-ta;
if(ta-x<=L && tb+x>=L) //能接上
{
find = true;
if(ta + x >= L) L += len;
else if(ta + x < L) L = tb+x;
tmp.erase(tmp.begin()+i);
break;
}
}
if(!find || L>=maxn) break;
}
if(L>=maxn) return true;
return false;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
{
node temp;scanf("%d%d",&temp.l,&temp.r);
temp.l*=2;temp.r*=2; //输入的区间都是整数,最小的小数是0.5 先乘2再除2 **
reg.push_back(temp);
}
sort(reg.begin(),reg.end(),cmp); //按右端点升序排序 **
int l=0,r=2*1e4;
double ans=0;
while(l<r)
{
int mid=(l+r)>>1;
cout<<l<<" "<<r<<" "<<mid<<endl;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l/2;
}