1002 Game (贪心模拟)

C语言题库

共 3165字,需浏览 7分钟

 ·

2021-05-02 13:54

1002 Game (贪心模拟)



Time Limit: 2000/1000 MS (Java/Others)


Memory Limit: 32768/32768 K (Java/Others)


Problem Description


度度熊在玩一个好玩的游戏。游戏的主人公站在一根数轴上,他可以在数轴上任意移动,对于每次移动,他可以选择往左或往右走一格或两格。现在他要依次完成 n 个任务,对于任务 i,只要他处于区间 [ai,bi]上,就算完成了任务。度度熊想知道,为了完成所有的任务,最少需要移动多少次?度度熊可以任意选择初始位置。


Input


第一行一个整数 T (1≤T≤10)表示数据组数。对于每组数据,第一行一个整数 n (1≤n≤1000) 表示任务数。接下来 n 行,第 iii 行两个整数 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。

题意分析:

给出n个区间,初始位置可选,依次到达相应的区间,每次可以移动一格或两格,求最小步数。


解题思路:

因为只要在这个区间中就可以完成任务,第一次的位置可选,所以初始位置可以选前几个任务的相交区间中,这样一次可以完成更多的任务, 此时若所以任务都完成即可结束,否则继续计算。



此时前面所有任务的相交区间是一个可选区间,也就是说初始位置可以选这个区间中的任意一个数,下一个任务不会和此区间重合,因为重合的区间会在前面计算在内,很容易想到如果下一任务在区间右侧,应该选最靠右的点,同理如果下一任务在区间左侧,应该选最靠左的点。


此时位置已经确定,在考虑任务时,在此区间内自然不用考虑,所以只看两种情况,用sum代表当前位置,两种情况为sum>b[i]和sum < a[i]。


在此有一个可移动步数,如果现在两步两步的移动可以到达箭头指向的地方,下一任务如果是第3个的左边区间,那么这样移动是对的,但如果是右边区间,那么之前移动的最后的2步应该改成1步,也就是说向右移动1步可以使贪心策略最佳,如果这个区间只有一个点,就不能移动。


上面考虑的是下一任务在sum左边的情况,在sum右边时同样可以推出来。


代码:

#include <stdio.h>
#include <algorithm>
#define N 1020
using namespace std;
int a[N], b[N];
int main() {
int t, n, l, r, i;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
scanf("%d%d", &a ,&b);

for(i=1; i<n; i++)
scanf("%d%d", &a[i], &b[i]);
l=a[0];r=b[0];
for(i=1; i<n; i++) { //选相交区间
if(max(l, a[i])>min(r, b[i]))
break;
l=max(l, a[i]);
r=min(r, b[i]);
}
if(i==n) //所有任务完成,结束
{
printf("0\n");
continue;
}
int ans=0, sum;

if(b[i]<l)
sum=l;
else sum=r;
int temp=0;

for(; i<n-1; i++) //没有考虑最后一个,因为要用到 i+1 项任务
{
if(sum>b[i]) {
if (temp==-1) //步数可以移动
sum--;
ans+=(sum-b[i]+1)/2; //更新步数
if((sum-b[i])%2==1 && b[i]-a[i]>=1) //判断区间只有一个点的情况
temp=-1; //更新可以移动的步数
else temp=0;
sum=b[i]; //更新位置
}
else if(sum < a[i]) {
if (temp==1)
sum++;
ans+=(a[i]-sum+1)/2;

if((a[i]-sum)%2==1 && b[i]-a[i]>=1)
temp=1;
else temp=0;
sum=a[i];
}
else {
if (sum==a[i] && temp==-1)
temp=0;
else if (sum==b[i] && temp==1)
temp=0;
}
}
if(sum>b[i]) { //考虑最后一个
if (temp==-1)
sum--;
ans += (sum-b[i] + 1)/2;
}
else if(sum<a[i]) {
if (temp==1)
sum++;
ans+=(a[i]-sum+1)/2;
}

printf("%d\n",ans);
}
return 0;
}


浏览 12
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报