hdu6669 Game【贪心】【2019百度之星初赛一 B题】

博客解析了HDU6669 Game问题,这是一个关于任务区间移动的题目。作者指出,一些解决方案通过合并区间来计算步数是错误的,并给出了正确思路:维护当前所在区间[l, r],每次加入任务区间后更新,考虑重合部分和步数奇偶性来确定最优移动策略。并提供了hack数据证明其方法的正确性。" 125124935,10895027,Vue组件深入解析:定义、注册与嵌套,"['vue.js', 'javascript', 'webpack']
摘要由CSDN通过智能技术生成

题意:

给你n个任务区间 [ a i , b i ] [a_{i}, b_{i}] [ai,bi] 1 ≤ a i ≤ b i ≤ 1000000 1\le a_{i} \le b_{i} \le 1000000 1aibi1000000
你可以选择起点,每次你可以 向左 走一步或者两步,或者向右走两步或一步
请你依次到达所有的区间,最少需要多少次

思路:

比赛的时候看错两次题,第一次没有看到依次,比赛过程中看到了,把排序贪心改掉了,但是还是看错了题,我一直以为是只能向左一步和向右两步…
参考博客
我看到好多博客都是直接先合并所有重合的区间,然后再进行移动算次数,这种写法明显不对,但是数据太水,居然给过了
hack数据如下

4
1 2
4 5
5 6
10 10

答案应该为4,但是如果提前合并了区间,答案就为5

我的思路为:
用两个数字l, r,代表每一次执行任务前我的点在区间 [ l , r ] [l, r] [l,r]之间,由于起点可以随意起,于是我初始化为l = 1, r = 1000000,每次加入新的任务区间,更新当前点所在的区间,已经加入到这个区间的最短距离
1.如果有重合的部分就直接取重合的部分,不用移动
2.如果不重合,判断该区间与任务区间的距离为偶数则直接到达任务区间的端点最优,如果为奇数,那我们走一样的步数可以到达任务区间的的端点和相邻的点,则将区间更新为任务区间的端点和其相邻的点(建立在下一个任务区间长度大于1的前提下)

为什么我们要直接记录点的区间到不能直接取任务区间的端点作为到达的终点,因为如果存在当前区间与下一个任务区间长度为奇数,而我们用同样的步数可以到达两个终点,但是我们如果选择任务区间的端点来作为终点,如果下下任务区间与该端点的距离为奇数且比下下任务区间与该端点的相邻点的距离的大的话就不是最优的

#include<bits/stdc++.h>
using namespace std;
int l, r;
int solve(int x, int y) {
	int ll = max(x, l);
	int rr = min(y, r);
	if(ll <= rr) {
		l = ll;
		r = rr;
		return 0;
	}
	int res;
	if(y < l) { //新的任务区间在左边
		res =  (l - y + 1) / 2;
		r = y;
		if((l - y) % 2 == 1 && x != y) {
			l = y - 1;
		} else {
			l = y;
		}
	} else {//新的任务区间在右边
		res = (x - r + 1) / 2;
		l = x;
		if((x - r) % 2 == 1 && x != y) {
			r = x + 1;
		} else {
			r = x;
		}
	}
	return res;
}
int main() {
	int t, n, x, y;
	cin>>t;
	while(t--) {
		cin>>n;
		int ans = 0;
		l = 1, r = 1000000;
		while(n--) {
			cin>>x>>y;
			ans += solve(x, y);
		}
		cout<<ans<<endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值