Game 2019 年百度之星·程序設計大賽 - 初賽一 思維

Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 547    Accepted Submission(s): 107


 

Problem Description

度度熊在玩一個好玩的遊戲。
遊戲的主人公站在一根數軸上,他可以在數軸上任意移動,對於每次移動,他可以選擇往左或往右走一格或兩格。
現在他要依次完成 n 個任務,對於任務 i,只要他處於區間 [ai,bi] 上,就算完成了任務。
度度熊想知道,爲了完成所有的任務,最少需要移動多少次?
度度熊可以任意選擇初始位置。

 

 

Input

第一行一個整數 T (1≤T≤10) 表示數據組數。
對於每組數據,第一行一個整數 n (1≤n≤1000) 表示任務數。
接下來 n 行,第 i 行兩個整數 ai,bi (1≤ai≤bi≤1000000) 表示任務對應的區間。

 

 

Output

對於每組數據,一行一個整數表示答案。

 

 

Sample Input


 

1 2 1 10 20 30

 

 

Sample Output


 

5 樣例描述 選取10爲起點,經過的軌跡爲10-12-14-16-18-20。

 

思路:首先注意一點是區間是可以相交重疊覆蓋的。所以我們第一步應該是將區間相交重疊覆蓋的先合併。合併之後區間就是各不相交的了。我們區間的起點也是不一定的,但是取件的順序是一定的。那麼我們就取第一個區間中離第二個區間最近的點爲起點。我們就可以跳了。要求步數最少,那麼我們貪心地每次跳2格。要注意,區間間隔爲奇數的情況,如果跳2不跳1也能跳進下一個區間並且離下下個區間更近那麼我們就選擇跳2。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
struct node{
	int l;
	int r;
}a[maxn],b[maxn];
int main()
{
	int n,t,cnt,id,len,ans;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d%d",&a[i].l,&a[i].r);
		b[1]=a[1];cnt=1;ans=0;
		for(int i=2;i<=n;i++)
		{
			if(b[cnt].r<a[i].l||b[cnt].l>a[i].r) b[++cnt]=a[i];
			else {b[cnt].l=max(b[cnt].l,a[i].l);b[cnt].r=min(b[cnt].r,a[i].r);}
		}
		if(b[2].r<b[1].l) id=b[1].l;
		else id=b[1].r;
		for(int i=2;i<=cnt;i++)
		{
			if(b[i].r<b[i-1].l)
			{
				len=id-b[i].r;id=b[i].r;
				if(len&1&&b[i].l<id&&i+1<=cnt&&b[i+1].r<b[i].l)
				{
					len++;id--;
				}
			}
			else
			{
				len=b[i].l-id;id=b[i].l;
				if(len&1&&b[i].r>id&&i+1<=cnt&&b[i+1].l>b[i].r)
				{
					len++;id++;
				}
			}
			ans+=len/2;
			if(len&1) ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章