• Milking Cows


    描述

    三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶。第一个农民在300时刻(从5点开始计时,秒为单位)给他的牛挤奶,一直到1000时刻。第二个农民在700时刻开始,在 1200时刻结束。第三个农民在1500时刻开始2100时刻结束。期间最长的至少有一个农民在挤奶的连续时间为900秒(从300时刻到1200时刻),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300时刻(从1200时刻到1500时刻)。

    你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两点(均以秒为单位):

    • 最长至少有一人在挤奶的时间段。
    • 最长的无人挤奶的时间段。(从有人挤奶开始算起)

    格式

    PROGRAM NAME: milk2

    INPUT FORMAT:

    (file milk2.in)

    Line 1:

    一个整数N。

    Lines 2..N+1:

    每行两个小于1000000的非负整数,表示一个农民的开始时刻与结束时刻。

    OUTPUT FORMAT:

    (file milk2.out)

    一行,两个整数,即题目所要求的两个答案。

    SAMPLE INPUT

    3
    300 1000
    700 1200
    1500 2100
    

    SAMPLE OUTPUT

    900 300
    
    
    
    
    
    
    题解:
    我的思路是合并重叠部分。
    代码实现:
    View Code
     1 /*
    2 ID:10239512
    3 PROG:milk2
    4 LANG:C++
    5 */
    6
    7 #include<iostream>
    8 #include<fstream>
    9 #include<string>
    10 using namespace std;
    11
    12 ifstream fin("milk2.in");
    13 ofstream fout("milk2.out");
    14
    15 int a[5001][2],n;
    16
    17 int main()
    18 {
    19 int i,j;int ans1=0,ans2=0;
    20 fin>>n;
    21 int x=100000000,y=0,z=0,t=0;
    22 for(i=1;i<=n;i++)
    23 {fin>>a[i][1]>>a[i][2];
    24 if(a[i][1]<x) {x=a[i][1];z=i;}
    25 if(a[i][2]>y) {y=a[i][2];t=i;}
    26 if(a[i][2]-a[i][1]>ans1) ans1=a[i][2]-a[i][1];}
    27
    28 if(n==1) {fout<<a[1][2]-a[1][1]<<" "<<0<<endl;return 0;}
    29
    30 for(i=1;i<=n;i++)
    31 for(j=1;j<i;j++)
    32 if(a[j][1]>a[i][1])
    33 {swap(a[i][1],a[j][1]);swap(a[i][2],a[j][2]);}
    34
    35 for(i=1;i<n;i++)
    36 if(a[i][2]>=a[i+1][1])
    37 {a[i+1][2]=max(a[i][2],a[i+1][2]);a[i+1][1]=a[i][1];if(ans1<a[i+1][2]-a[i+1][1]) ans1=a[i+1][2]-a[i+1][1];}
    38 else
    39 {
    40 if(ans2<a[i+1][1]-a[i][2])
    41 ans2=a[i+1][1]-a[i][2];
    42 }
    43
    44 if(t==z) ans2=0;
    45 fout<<ans1<<" "<<ans2<<endl;
    46 //system("pause");
    47 return 0;
    48
    49 }


    另外nocow上还有几种方法很好啊:

    标记数组(哈希)

    1e6的范围,开一个布尔数组完全可以,有人为TRUE,无人为FALSE,注意边界即可。最后线性扫描即可。

    做些优化

    预处理:

     建立一个数组a。
     读入,若为起点将a[i]加1,若为终点将a[i]减1。
     (这时顺便找出总的起点与终点);
    

    算法开始:

     将数组扫一遍(注意从总的起点扫到总的终点),这时将x(初始为0)加上a[i]。
      若遇到x由0变1,或由1变0,
      将这个点计入数组ans[]。
      然后再将ans扫描一遍,大家可能都想到了:
       若i为奇数,a[i+1]-a[i] 应该是有人的时间间隔;
       若i为偶数,反之。
    哈希表的解法:
    View Code
     1 /*
    2 ID: aikilis1
    3 LANG: C
    4 PROG: milk2
    5 */
    6 #include <stdio.h>
    7 #include <memory.h>
    8 int main(void)
    9 {
    10 int n,i,a,b,j,m1=1000000,m2=0,max[2]={0,0};
    11 char hash[1000000];
    12 freopen("milk2.in","r",stdin);freopen("milk2.out","w",stdout);
    13 memset(hash,0,sizeof hash);
    14 scanf("%d",&n);
    15 for (i=0;i<n;++i)
    16 {
    17 scanf("%d%d",&a,&b);
    18 --b;
    19 if (a<m1) m1=a;
    20 if (b>m2) m2=b;
    21 for (j=a;j<=b;++j) hash[j]=1;
    22 }
    23 for (i=m1;i<m2;i+=j)
    24 {
    25 for (j=0;hash[i+j]==hash[i];++j);
    26 if (j>max[hash[i]]) max[hash[i]]=j;
    27 }
    28 printf("%d %d\n",max[1],max[0]);
    29 fclose(stdin);fclose(stdout);
    30 return 0;
    31 }


  • 相关阅读:
    MS SQL入门基础:使用SQL Server Profiler
    收藏夹路径设置
    MS SQL入门基础:数据转换服务基本概念
    MS SQL入门基础:复制的概述和术语
    MS SQL入门基础:创建备份设备
    巧用ASP生成PDF文件
    MS SQL入门基础:sql 警报
    MS SQL入门基础:基于HTTP的数据访问
    MS SQL入门基础:XML文档与数据库表
    MS SQL入门基础:复制监视器
  • 原文地址:https://www.cnblogs.com/noip/p/2369786.html
Copyright © 2020-2023  润新知