2019百度之星·程序设计大赛-初赛一 —— 1002 Game

Problem Description

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

Input

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

题解思路:

(1)首先应当注意到题目中“依次完成”这四个大字!

(2)既然前提是依次完成,且还需要最短移动次数,那我们找出给出的区间之间的交集

(3)通过不断的合并前后的区间可以得到最后的互不相交的各个区间

(4)初始位置的选择需要考虑第一个区间和第二个区间的关系(这里的区间都是合并后的区间),如果第一个区间在第二个区间的左侧,那么初始点就选择第一个区间的右端点,反之选择左端点。

(5)确定了起点之后便是依次完成任务的循环,循环次数应当为区间数减一(最后一个区间单独计算)

(6)同样每次移动之前要判断当前位置和目标区间的位置关系,这样便可找出区间和当前位置的最短距离

(7)找到最短距离之后要判断是奇数还是偶数,如果距离是偶数,那就两步两步走到端点位置即可

(8)如果距离是奇数,开始判断:[1]目标区间是否为单值;[2]当前位置是否在目标区间与下一个目标区间之间。如果满足这两个条件其中一个,那我们移动后的落点就应当在目标区间的端点上

(9)如果(8)的条件一个不满足,那我们就可以用两步两步走到目标区间之内,然后继续下一次循环

(10)当结束循环后直接计算当前位置和最后一个区间的距离即可。

AC代码如下:

#include<iostream>
#include<vector>
using namespace std;
typedef struct
{
    int star;
    int end;
} Point;
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        Point t;
        t.star = 0;
        t.end = 1000005;
        vector<Point>T;
        int a,b;
        for(int i=0; i<n; i++)
        {
            cin>>a>>b;
            if(a<=t.end&&b>=t.star)
            {
                t.star = t.star>a?t.star:a;
                t.end = t.end<b?t.end:b;
            }
            else
            {
                T.push_back(t);
                t.star = a;
                t.end = b;
            }
        }
        T.push_back(t);
        int sum=0,S;
        if(T.size()>1)
        {
            S = T[0].star<T[1].star?T[0].end:T[0].star;
            for(int j=1; j<T.size()-1; j++)
            {
                if(S>T[j].star)
                {
                    if((S-T[j].end)%2==0)
                    {
                        sum += (S-T[j].end)/2;
                        S = T[j].end;
                    }
                    else
                    {
                        if((T[j].star<T[j+1].star)||(T[j].star==T[j].end))
                        {
                            sum += (S-T[j].end)/2+1 ;
                            S = T[j].end;
                        }
                        else
                        {
                            sum += (S-T[j].end+1)/2 ;
                            S = T[j].end-1;
                        }
                    }
                }
                else
                {
                    if((T[j].star - S)%2==0)
                    {
                        sum += (T[j].star - S)/2;
                        S = T[j].star;
                    }
                    else
                    {
                        if(T[j].star>T[j+1].star||T[j].star==T[j].end)
                        {
                            sum += (T[j].star - S)/2+1 ;
                            S = T[j].star;
                        }
                        else
                        {
                            sum += (T[j].star - S + 1)/2 ;
                            S = T[j].star+1;
                        }
                    }
                }
            }
            if(S<T[T.size()-1].star)sum += (T[T.size()-1].star +1-S)/2;
            else sum += (S- T[T.size()-1].end +1)/2;
        }
        cout<<sum<<endl;
    }
    return 0;
}

 

©️2020 CSDN 皮肤主题: 点我我会动 设计师:上身试试 返回首页