NYOJ_1036 非洲小孩 HDU_1687 Lucky Light

这两道题比较有代表性,一开始在做非洲小孩这道题目时,用的是按照起始时间从小到大排列,在贪心选取。思考一段时间过后,就发现其实题目是在每个区间中都包含一个点,点的最少数目就是答案。显然必须要按照结束时间从小到大排序。

区间选点:(右端排序)给n个闭区间[ai,bi], 在数轴上选尽量少的点,使每个区间内至少有一个点。NYOJ1036

区间覆盖:(左端排序)给n个闭区间[ai,bi], 求有多少块连续区间。HDU1687

NYOJ 1036:

描述
家住非洲的小孩,都很黑。为什么呢?
第一,他们地处热带,太阳辐射严重。
第二,他们不经常洗澡。(常年缺水,怎么洗澡。)
现在,在一个非洲部落里,他们只有一个地方洗澡,并且,洗澡时间很短,瞬间有木有!!(这也是没有的办法,缺水啊!!)
每个小孩有一个时间段能够洗澡。并且,他们是可以一起洗的(不管你是男孩是女孩)。
那么,什么时间洗澡,谁应该来洗,由谁决定的呢?那必然是他们伟大的“澡”神啊。“澡”神有一个时间表,记录着该部落的小孩,什么时候段可以洗澡。现在,“澡”神要问你,一天内,他需要最少开启和关闭多少次洗澡的水龙头呢?因为,开启和关闭一次水龙头是非常的费力气的,即便,这也是瞬间完成的。
输入
多组数据
第一行一个0<n<=100。
接下来n行,每行一个时间段。H1H1:M1M1-H2H2:M2M2,24小时制。
保证该时间段是在一天之内的。但是,不保证,H1H1:M1M1先于H2H2:M2M2。
输出
题目描述,“澡”神最少需要开启和关闭多少次水龙头呢?
样例输入
1
00:12-12:12
2
00:12-12:12
14:00-12:00
样例输出
1
1
代码:

#include<string.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<stack>
#include<map>
#include<queue>
#include<vector>
#include<cctype>
using namespace std;

struct NODE
{
    int st,end;
}time1[190];

bool cmp(struct NODE a, struct NODE b)
{
    return a.end < b.end;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int len=0;
        
        while(n--)
        {
            int hh1,mm1,hh2,mm2;
            scanf("%d:%d-%d:%d",&hh1,&mm1,&hh2,&mm2);
            mm1+=hh1*60;                                                                                   //时间化成分钟来比较会更加方便
            mm2+=hh2*60;
            if(mm1>mm2)
            {
                swap(mm1,mm2);
            }
            time1[len].st = mm1;
            time1[len++].end = mm2;            
        }
        sort(time1,time1+len,cmp);    
        
        int ans=1;
        int hh=time1[0].end;
        for(int i=1;i<len;i++)
        {
            if(time1[i].st > hh)
            {
                ans++;
                hh=time1[i].end ;
            }            
        }
        printf("%d\n",ans);            
    }    
    return 0;
}

HDU 1687

Problem Description
We have a (point) light source at position (xL, yL) with yL > 0, and a finite series of line segments, all of finite non-zero length, given by the coordinates of their two endpoints. These endpoints are all different. The line segments are all situated above the x-axis (y > 0).

The segments cast their shadows onto the x-axis. We assume that the shadows of two segments either do not overlap at all, or have an overlap that has some non-zero width (they do not just touch). We also assume that for each segment its shadow is more than just one point, i.e., there is no segment that is directed toward the light source. The height of the light source (yL) is at least 1 unit larger than the y-coordinates of the endpoints of the line segments. This guarantees that indeed each line segment has a bounded shadow on the x-axis.

The collection of shadows divides the x-axis into dark and lighted areas (intervals). The problem is to determine the number of lighted areas — which is at least 2 (if there is at least one line segment, otherwise it is 1).

In the picture below the three line segments A, B and C cause three lighted areas, as indicated.


 

Input
The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format:

One line with one integer n with 0 ≤ n ≤ 100: the number of line segments.
One line with two integers xL and yL, the coordinates of the light source, separated by a single space. The coordinates satisfy -100 ≤ xL ≤ 100 and 1 ≤ yL ≤ 1,000.
n lines, each containing four integers xi, yi, ui and vi, separated by single spaces, that specify x- and y-coordinates of the two endpoints (xi, yi) and (ui, vi) of the ith line segment, where -100 ≤ xi, ui ≤ 100 and 0 < yi, vi < yL, for 1 ≤ i ≤ n.
 

Output
For every test case in the input file, the output should contain a single number, on a single line: the number of lighted areas.

 

Sample Input
  
  
2 3 50 60 55 45 30 35 64 39 92 18 20 30 40 16 2 -10 50 -10 1 10 11 -10 11 10 1
 

Sample Output
  
  
3 2

题目大意:

题意:有一个光源,下面有很多放置的板子,问光线被板子分割之后在地上能产生多少块亮区(看题中的图就能看懂)。

分析:这个题的做法和省选第一天的C题很像,由于是求在地面上,也就是一条直线上的亮区,我们可以求出地面上被木板遮挡形成的暗区的左坐标和右坐标,然后合并区间就可以了。而求地面上的坐标,可以用相似三角形,若光源为(sx,sy),点为(x1,y1)和(x2,y2),则地面上的坐标为:sx-(sx-s1)*sy/(sy-y1)和sx-(sx-s2)*sy/(sy-y2),需要注意的是两个坐标中较小的为左,大的为右,最好不要根据输入的x1,y1,x2,y2的大小关系去判定哪个为左哪个为右,这样很容易落下某种特殊情况。


代码:

#include<string.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<ctime>
#include<cstdio>
#include<stack>
#include<map>
#include<queue>
#include<vector>
#include<cctype>
using namespace std;

struct NODE
{
    double st,end;
}node[190];

bool cmp(struct NODE a,struct NODE b)
{    
    return a.st < b.st;
}

int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        int n;
        scanf("%d",&n);
        double scx,scy;
        scanf("%lf%lf",&scx,&scy);
        for(int i=0;i<n;i++)
        {
            double x1,y1,x2,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            x1=(scy*x1-scx*y1)/(scy-y1);
            x2=(scy*x2-scx*y2)/(scy-y2);
            node[i].st = min(x1,x2);
            node[i].end = max(x1,x2);            
        }
        sort(node,node+n,cmp);
        int ans=(n>0 ? 2 : 1 );
        double temp = node[0].end;
        for(int i=1;i<n;i++)
        {
            if(node[i].st > temp)
            {
                ans++;
                temp=node[i].end ;
            }
            else if(node[i].st<temp && node[i].end > temp)
            {
                temp=node[i].end;
            }
        }
        cout<<ans<<endl;
    }    
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值