问题:
    三个农民在5点起床,去畜棚帮3头奶牛挤奶。第一个农民在第300秒(从早上五点开始算起)开始挤他的奶牛,并在第1000秒结束。第二农民开始时间为700,结束为1200。第三个农民开始为1500,结束为2000。至少有一个农民在挤奶的最长的持续时间为900(从300到1200)。没有农民挤奶的最长持续时间为300(1500减去1200)。

写一个程序通过计算N的农民挤N头奶牛的开始和结束时间的列表(以秒计算),获得以下结果:

  • 持续最长的至少有1个农民在挤奶的时间间隔。
  • 没有农民挤奶的最长持续时间(在挤奶开始之后)。

程序名:milk2

输入格式

行 1:

一个整数

行 2..N+1:

T小于1000000的正整数, 在0500之后以秒计算的开始和结束时间。

分析:
农民1的时间区间为:[300,1000]
农民2的时间区间为:[700,1200]
农民3的时间区间为:[1500,2000]
合并区间可以得到[300,1200],[1500,2000]
显然合并后区间的长度中最大值便是我们所求的最长持续时间。这里是max{900,500}
所以区间的两两间的间隔中最大值便是我们所求的最长中断时间。这里是max{300}

所以我们只有获得一个合并后的区间,再求以上两个值的集合后取相应的最大值就可以得到本题的解。
农民的区间排列并非有序,农民2的区间可以是[100,500]。所以首先我们需要对区间左端进行升序排序。
对区间的右端排序之后,对于相邻的两个区间[a(n),b(n)]与[a(n+1),b(n+1)],由于a(n)<=a(n+1)(已知a(n)<=b(n)),
故这两个区间的关系只有包含,相交,以及无交集三个关系。可以得到
包含:a(n+1)<=b(n) b(n+1)<=b(n)
相交:a(n+1)<=b(n)
无交集:a(n+1)>b(n)
遍历两次依据这三种关系,做适当操作即可将合并区间。
合并之后,除去那些无用的区间(事实上在合并的时候可以将那些被合并的区间中后一个区间长度变为0),获得一个新的区间列表,在这个新的区间列表找寻最大长度区间和最大中断区间间隔即可获得解。
具体d的c++代码如下:

#include < iostream >
#include < fstream >
#include < string >

using namespace std;

bool IsInRange( int a, int b, int n);

int main()
{
    ifstream fin ("milk2.in");
    ofstream fout ("milk2.out");
    int n;
    int max_c=0; // max continuous time
    int max_b=0; // max break time
    int a[5000][2];
    int fa[5000][2];//过滤a后的数组
    int len=0;
    int c=0;
    int b=0;
    fin>>n;
    for(int i=0;i<n;i++)//获得输入
    {
        fin>>a[i][0]>>a[i][1];
    }
    //先排序,以farm开始的时间即区间的左端点从小到大排序
    for(int i=1;i<n;i++)
    {
        int a1,a2;
        if(a[i][0]<a[i-1][0])
        {
            int k=i;
            while(a[k][0]<a[k-1][0])//swap,交换
            {
                a1=a[k][0];
                a2=a[k][1];
                a[k][0]=a[k-1][0];
                a[k][1]=a[k-1][1];
                a[k-1][0]=a1;
                a[k-1][1]=a2;
                k--;
                if(k==0)
                    break;
            }
        }
    }
    //合并1.交 2.包含 3.无交集
    for(int i=0;i<n-1;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            int s0=a[i][0]; //初始化两个区间
            int e0=a[i][1];
            int s1=a[j][0];
            int e1=a[j][1];
            if(IsInRange(s0,e0,s1))//判断左端点
            {
                if(IsInRange(s0,e0,e1))//判断右端点,包含关系,合并区间
                {
                    a[j][0]=a[i][1]; //[3,9],[4,7]->[3,9][3,3]
                    a[j][1]=a[i][0];
                    a[j][0]=a[i][0];
                }
                else//交集
                {
                    a[i][1]=a[j][1]; //[3,5],[4,7]->[3,7],[3,3]
                    a[j][0]=a[i][0];
                    a[j][1]=a[i][0];
                }
            }
            else //无交集
            {
                break;
            }
        }
    }
    len=0;
    for(int i=0;i<n;i++)//移除[3,3],[12,12]这样的无效项
    {
        int t1=a[i][0];
        int t2=a[i][1];
        if(t1!=t2)
        {
            fa[len][0]=t1;
            fa[len][1]=t2;
            len++;
        }
    }
    max_c=a[0][1]-a[0][0];//第一个区间的长度
    max_b=0; //初始间隔为0
    int k=0;
    for(int i=0;i<n-1;i++)
    {
        int c=fa[i+1][1]-fa[i+1][0];//区间长度
        int b=fa[i+1][0]-fa[i][1];//区间间隔
        if(c>max_c) //保留区间长度的最大值
        {
            max_c=c;
        }
        if(b>max_b) //保留区间间隔的最大值
        {
            max_b=b;
            b=0;
        }
    }
    fout<<max_c<<" "<<max_b<<endl;
    return 0;
}

bool IsInRange( int a, int b, int n)  // 判断n是否属于[a,b]
{
    if(n>=a&&n<=b)
    {
        return true;
    }
    else
    {
        return false;
    }
}

以上算法可以优化,不用合并区间,直接寻找解也可以。
代码如下:

#include < iostream >
#include < fstream >
#include < string >

using namespace std;

bool IsInRange( int a, int b, int n);
void QuikSort( int a[][ 2 ], int left, int right);

int main()
{
    ifstream fin ("milk2.in");
    ofstream fout ("milk2.out");
    //ofstream ftest("m.out");
    int n;
    int max_c=0; // max continuous time
    int max_b=0; // max break time
    int a[5000][2];
    int len=0;
    int c=0;
    int b=0;
    fin>>n;
    fin>>a[0][0]>>a[0][1];
    for(int i=1;i<n;i++)//获得输入
    {
        fin>>a[i][0]>>a[i][1];
    }
    QuikSort(a,0,n-1);
    int cur[2];
    cur[0]=a[0][0];
    cur[1]=a[0][1];
    max_c=a[0][1]-a[0][0];//第一个区间的长度
    max_b=0; //初始间隔为0
    for(int i=1;i<n;i++) //寻找最大最小值
    {
        if(a[i][0]>cur[1])
        {
            b=a[i][0]-cur[1];
            if(b>max_b) max_b=b;
            c=cur[1]-cur[0];
            if(c>max_c) max_c=c;
            cur[0]=a[i][0];
            cur[1]=a[i][1];
        }
        else
        {//3,67, 4,87, 5,77  3->87 3->87
            if(a[i][1]>cur[1]) cur[1]=a[i][1];
        }
    }
    fout<<max_c<<" "<<max_b<<endl;
    return 0;
}

void QuikSort( int a[][ 2 ], int left, int right) // 快速排序
{
    if(left<right)
    {
        int s=a[left][0]; //哨兵,即参考值X
        int s1=a[left][1];
        int i=left+1;
        int j=right;
        while(true)
        {
            while(a[i][0]<s&&i<right)
                i++;
            while(a[j][0]>s&&j>=0)
                j--;
            if(i>=j) break;
            int a1,a2;
            a1=a[i][0];
            a2=a[i][1];
            a[i][0]=a[j][0];
            a[i][1]=a[j][1];
            a[j][0]=a1;
            a[j][1]=a2;
            i++;
            j--;
        }
        a[left][0]=a[j][0];
        a[left][1]=a[j][1];
        a[j][0]=s;
        a[j][1]=s1;
        QuikSort(a,left,j-1);
        QuikSort(a,j+1,right);
    }
}

bool IsInRange( int a, int b, int n)  // 判断n是否属于[a,b]
{
    if(n>=a&&n<=b)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Milking Cows【转帖】相关推荐

  1. Milking Cows 挤牛奶

    1.2.1 Milking Cows 挤牛奶 Time Limit: 1 Sec  Memory Limit: 64 MB Submit: 554  Solved: 108 [Submit][Stat ...

  2. [USACO 1.2.1] Milking Cows

    [题目描述] Milking Cows 挤牛奶 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300时刻(从5点开始计时,秒为单位)给他的牛挤奶,一直到1000时刻.第二个农民在700 ...

  3. 【USACO题库】1.2.1 Milking Cows挤牛奶

    一开始认为过不了,后来交就AC了. 1007. [USACO题库]1.2.1 Milking Cows挤牛奶 (File IO): input:milk.in output:milk.out 题目描述 ...

  4. 挤牛奶Milking Cows

    挤牛奶Milking Cows 这道题问的是有一条线段覆盖的最大区间和没有线段覆盖的区间. 先按照起点排序,然后从第二条线段开始判断.如果该线段的起点小于上一线段终点,则说明这两条线 段有重合部分,将 ...

  5. Milking Cows UASCO

    原题地址 Three farmers rise at 5 am each morning and head for the barn to milk three cows. The first far ...

  6. [USACO1.2]挤牛奶Milking Cows

    题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒.第二个农民在700秒开始,在 1200秒结束.第三个农民在1500秒开 ...

  7. USACO Training Section 1.2 挤牛奶Milking Cows

    题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒.第二个农民在700秒开始,在 1200秒结束.第三个农民在1500秒开 ...

  8. USACO 1.2 Milking Cows (枚举)

    标记数组(哈希) 1e6的范围,开一个char数组全然能够,有人为1,无人为0,注意边界就可以.最后线性扫描就可以. 时间复杂度,应该是O(n),n为最后结束的时间. 缺点就是--比較慢 /*ID:t ...

  9. 洛谷P1204 [USACO1.2]挤牛奶Milking Cows 前缀和

    这题数据比较水 暴搜都能够过去 1 #include <cstdio> 2 #include <cmath> 3 #include <cstdlib> 4 #inc ...

最新文章

  1. 圣诞夜,让你的代码都变成圣诞树吧!
  2. 转-项目管理心得:一个项目经理的个人体会、经验总结
  3. JsonObject的依赖
  4. 批处理 java环境_java环境配置简单批处理方法一键OK
  5. 三维数据平滑处理_关于CAD三维对象建模
  6. centos用php上传文件,WBB - Centos下PHP无法Curl模拟Post上传文件的问题
  7. Java ==和equals有什么区别?
  8. 纪念第一次用vscode给go语言配置环境踩坑
  9. 网络安全之黑客入侵的步骤
  10. python Crypto.Cipher
  11. 迅捷pdf转换器:如何将pdf转换成word
  12. Invalid handle returned
  13. uniapp打包 云端服务器返回错误:请先完成企业实名认证,证明您是“****“的开发者。如有疑问,请发邮件到service@dcloud.io咨询
  14. [bzoj4796][CERC2016]Key Knocking_乱搞
  15. Vant2 源码分析之 vant-sticky
  16. 【西电—英美国家概况(英美概况/英美文化)2023第一学期】第六章参考课后答案
  17. linux xxx命令,linux命令ps aux|grep xxx详解
  18. 初中生直升高中定下来了?预计2023年全面落实?教育部的回应来了
  19. internet信息服务器连接怎么办,internet已连接但无法上网怎么办
  20. CTF 隐写工具Steghide

热门文章

  1. 编解码注入、二次注入、DNSlog盲注
  2. 如何树立正确的人生观、价值观、世界观?
  3. 流水灯循环点亮c语言程序,流水灯来回点亮程序(汇编和C)
  4. 2021卫辉高考成绩查询,卫辉中考成绩查询2021
  5. 15分钟看完:悉尼科技大学入选 CVPR 2021 的 9 篇论文,都研究什么?
  6. 操作系统真象还原第一章
  7. 计算机网络安全漏洞及防范措施论文,浅谈计算机网络安全漏洞及防范措施论文.doc...
  8. 【Codeforces 526F】【JZOJ4687】奇袭
  9. 上行参考信号-SRS
  10. 我的STC89C52单片机