zoukankan      html  css  js  c++  java
  • 【算法学习笔记】56.区间合并问题变形 SJTU OJ 1365 最少道路

    Description

    有一些同学在练习匀速跑,他们起点和速度各不相同,但约定好练习相同的时间。

    请根据给出的同学的初始位置和速度,计算至少需要多少条跑道才能保证同学之间互相不会相撞。在任何一个时间点两个不同的同学处在相同的位置均视为相撞。

    Input Format

    第一行:两个整数N和T。N (1 <= N <= 1,000,000) 代表总人数,T (1 <= T <= 1,000,000,000)代表所有人跑步的时间。

    第2 ~ (N+1)行:两个整数,第一个代表起始位置,第二个代表速度。

    Output Format

    一个整数,输出最小跑道数量。

    Sample Input:

    5 3
    0 1
    1 2
    2 3
    3 2
    6 1
    

    Sample Output:

    3


    其实。。这个题的数据是按照起点排序过后的,所以不必再进行排序了。
    判断两个人是否会相交,可以根据在直角坐标系中两条线段是否相交的关系来确定检查函数
    另外这个题的数据比较大,要用ULL,而且是每一个中间计算结果也要用ULL
    具体算法是有点类似于贪心算法
    策略就是每条新的道路尝试加入所有还未处理的人,如果都没法加入了,开一个新的道路。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long ULL;
    
    struct Period
    {
        ULL start;
        ULL end;
        bool done;
    };
    
    
    bool cmp_period(const Period& a,const Period& b){
        return a.start < b.start;
    }
    
    
    inline bool check(ULL s,ULL e,const Period& b){
        return ((s < b.start) and (e < b.end));
    }
    
    Period ps[1000000];
    
    int main(int argc, char const *argv[])
    {
        ULL N,T;
        cin>>N>>T;
        for (ULL i = 0; i < N; ++i)
        {
            scanf("%d",&ps[i].start);
            ULL v; scanf("%d",&v);
            ps[i].end = ps[i].start + v*T;
            ps[i].done = false;
        } 
        //sort(ps,ps+N,cmp_period);  //按照起点排序 
        ULL ans = 0;
        for (ULL i = 0; i < N; ++i) if(!ps[i].done)
        {
            ans++;//加入一个新跑道 
            ULL e = ps[i].end;
            ps[i].done = true;
            //此处的查找可以优化成二分查找 因为是排序过的
            for (ULL j = i+1; j < N; ++j) if(!ps[j].done)
            {
                if(check(ps[i].start,e,ps[j])){//判断是否会香蕉
                    //如果不会相交
                    e = ps[j].end; //类似区间合并
                    ps[j].done = true;
                }
            }
        }
    
        cout<<ans<<endl;
        return 0;
    }

    标准程序如下:

    #include <iostream>
    #include <vector>
    #include <algorithm>
     
    using namespace std;
     
    int main() {
      int N, T;
      cin >> N >> T;
     
      vector<long long> A;//存储道路
      for (int i = 0; i < N; i++) {
        long long x, s;
        cin >> x >> s;//读入起点x和速度s
        x = -(x + s * T); //设置x为终点的负数
        //如果没有一个道路 或者 
        //如果该人的终点 <= 最后一个道路的终点 就要新建一个道路
        //原因是因为最后一个道路的终点肯定是最大的
        if (A.empty() || (-A.back()) >= (-x) ) { 
          A.push_back(x);//新建一个道路 用终点的负数来标识道路
        } else {
          //二分查找 找到可以添加的道路
          *upper_bound(A.begin(), A.end(), x) = x; //把该人加入之前的某一个道路中
        }
      }
      cout << A.size() << endl;
      return 0;
    }
    标准程序



  • 相关阅读:
    vue中使用sass
    vue2项目使用axios发送请求
    css正方形贴图
    用vue-cli 工具搭建项目
    反调试与破反调试笔记
    低功耗蓝牙UUID三种格式转换
    【原创】Android 5.0 BLE低功耗蓝牙从设备应用
    金山助手流氓软件-被进程sjk_daemon.exe坑死
    bower安装教程
    intellij idea快捷键
  • 原文地址:https://www.cnblogs.com/yuchenlin/p/sjtu_oj_1365.html
Copyright © 2011-2022 走看看