贪心3

I - 今年暑假不AC

“今年暑假不AC?” 
“是的。” 
“那你干什么呢?” 
“看世界杯呀,笨蛋!” 
“@#$%^&*%...” 

确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。 
作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目) 

Input输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。 
Output对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。

Sample Input

12
1 3
3 4
0 7
3 8
15 19
15 20
10 15
8 18
6 12
5 10
4 14
2 9
0

Sample Output

5

  思路:简单区间贪心,结构体排序,即可解决。
#include <iostream>
#include <algorithm>
#define LL long long
int const max_n=102;
using namespace std;
struct node{
    int x,y;
}num[max_n];

bool cmp(node a,node b)
{
    return a.y<b.y;
}
int main()
{
    while(1)
    {
        int n;
        scanf("%d",&n);
        if(n==0)break;
        for(int i=0;i<n;i++)
        {
            scanf("%d %d",&num[i].x,&num[i].y);
        }
        sort(num,num+n,cmp);
        int sum=1;    
        int start=num[0].y;
        for(int i=0;i<n;i++)
        {
            if(num[i].x>=start){start=num[i].y;sum++;}
        }
        printf("%d\n",sum);    
    }
    return 0;
}

K - Radar Installation

 Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point locating in the sea side. And any radar installation, locating on the coasting, can only cover d distance, so an island in the sea can be covered by a radius installation, if the distance between them is at most d. 

We use Cartesian coordinate system, defining the coasting is the x-axis. The sea side is above x-axis, and the land side below. Given the position of each island in the sea, and given the distance of the coverage of the radar installation, your task is to write a program to find the minimal number of radar installations to cover all the islands. Note that the position of an island is represented by its x-y coordinates. 

        

 

 

Figure A Sample Input of Radar Installations

Input
The input consists of several test cases. The first line of each case contains two integers n (1<=n<=1000) and d,
where n is the number of islands in the sea and d is the distance of coverage of the radar installation. This is
followed by n lines each containing two integers representing the coordinate of the position of each island.
Then a blank line follows to separate the cases. 

The input is terminated by a line containing pair of zeros
Output
For each test case output one line consisting of the test case number followed by the minimal number
of radar installations needed. "-1" installation means no solution for that case.
Sample Input

3 2
1 2
-3 1
2 1

1 2
0 2

0 0
  题目大意:有一条海岸线,如图中的x轴,x轴以下是陆地,x轴以上是海,海中有若干个小岛,让你在x轴上安装雷达,确定海岛的位置。多组输入,第一行输入小岛的数量和雷达的覆盖范围,遇到0 0 是输入结束;接下来是输入小岛的位置,对每组样例,输出将所有小岛都覆盖到最小用多少个雷达,若不可能覆盖所有雷达,输出-1。

        思路:这是一道区间贪心的变形题,既要考虑x轴还要考虑y轴。可以每次以一个点来判断,可以离它最远的雷达安装的位置(其实也就是x轴的距离,因为雷达只能安装在陆地上),默认要先设置一个点,然后开始遍历,当新的点的安装雷达的位置在上一个雷达安装位置所画的圆内,且新点的雷达安装位置在圆心左边时,可以知道新点的雷达安装位置可以覆盖到上一个达所能覆盖到的点,可以更新雷达的位置。反之,则判断新点的的位置能否被上一个雷达布置点覆盖,如果能则继续遍历,如果不能则布置一个新的雷达在该点。 代码如下:

#include <iostream>
#include <algorithm>
#include <math.h>
int const max_n=1002;
using namespace std;
struct node{
    int x,y;
}num[max_n];//用结构体来存储小岛信息

bool cmp(node a,node b)//结构体比较函数,x坐标较小的岛优先级高,x坐标相同时,y坐标大的优先级高
{
    if(a.x!=b.x)
        return a.x<b.x;
    return a.y>b.y;
}

int main()
{
    int k=0;//case标签计数器
    while(1)
    {
        int n,d;
        scanf("%d %d",&n,&d);//输入小岛数以及雷达范围
        if(n==0&&d==0)break;
        int sum=1,maxy=0;//因为会先以第一个岛的位置布置,所以设一开始就用了一个雷达,maxy是为了计算当某个岛的y坐标大于雷达范围时进行下一次循环
        for(int i=0;i<n;i++){scanf("%d %d",&num[i].x,&num[i].y);maxy=max(maxy,num[i].y);}
        if(maxy>d){printf("Case %d: -1\n",++k);continue;}
        sort(num,num+n,cmp);//结构体排序
        double xy=num[0].x+sqrt(d*d-num[0].y*num[0].y);//设置第一个雷达坐标
        int i=1;//第一个岛应安装的位置已经确定,所以设下标为1
        while(i<n)
        {
            double xx=num[i].x+sqrt(d*d-num[i].y*num[i].y);//新点的最远雷达安装位置
            if(xx<xy){xy=xx;i++;continue;}//若仍可以覆盖到上一个雷达所有能覆盖到的岛,则更新雷达位置
            if(pow(xy-num[i].x,2)+num[i].y*num[i].y>d*d){//若新点不被上一个雷达覆盖到,则安装一个新的雷达
                xy=xx;
                sum++;
            }
            i++;
        }
        printf("Case %d: %d\n",++k,sum);
    }
    return 0;
}
 

L - Saruman's Army

 

Saruman the White must lead his army along a straight path from Isengard to Helm’s Deep. To keep track of his forces, Saruman distributes seeing stones, known as palantirs, among the troops. Each palantir has a maximum effective range of R units, and must be carried by some troop in the army (i.e., palantirs are not allowed to “free float” in mid-air). Help Saruman take control of Middle Earth by determining the minimum number of palantirs needed for Saruman to ensure that each of his minions is within R units of some palantir.

Input

The input test file will contain multiple cases. Each test case begins with a single line containing an integer R, the maximum effective range of all palantirs (where 0 ≤ R ≤ 1000), and an integer n, the number of troops in Saruman’s army (where 1 ≤ n ≤ 1000). The next line contains n integers, indicating the positions x1, …, xnof each troop (where 0 ≤ xi ≤ 1000). The end-of-file is marked by a test case with R = n = −1.

Output

For each test case, print a single integer indicating the minimum number of palantirs needed.

Sample Input

0 3
10 20 20
10 7
70 30 1 7 15 20 50
-1 -1

Sample Output

2
4

Hint

In the first test case, Saruman may place a palantir at positions 10 and 20. Here, note that a single palantir with range 0 can cover both of the troops at position 20.

In the second test case, Saruman can place palantirs at position 7 (covering troops at 1, 7, and 15), position 20 (covering positions 20 and 30), position 50, and position 70. Here, note that palantirs must be distributed among troops and are not allowed to “free float.” Thus, Saruman cannot place a palantir at position 60 to cover the troops at positions 50 and 70.

  题意:一个将军带兵在一条直线上新军,路上遇到了危险,需要给士兵们加持buff,已知buff是有范围,且只能加持在直线上某个士兵的身上。问最少需要给几个士兵加持buff。多组输入,第一行输入buff范围,有多少个士兵,输入-1 -1 输入结束;第二行输入士兵位置。

  思路:对士兵位置进行预处理,排序,参照上题中海岛的方法,遍历士兵位置,更新buff的位置,但要注意,buff只能加在已有的士兵身上,所以判断条件要从最开始的士兵开始,当以新的士兵的位置更新buff位置,导致有士兵脱离了范围时,就要新加持一个buff。代码如下:

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#include <utility>
#define LL long long
int const max_n = 1002;
using namespace std;
int num[max_n];

int main()
{
    int r, n;
    while (scanf("%d %d", &r, &n) == 2)
    {
        if (r == -1 && n == -1)break;
        int  sum = 1;
        for (int i = 0; i < n; i++)
        {
            scanf("%d", &num[i]);
        }
        sort(num, num+n);
        int p = num[0], i = 1,t=0;
        while (i < n)
        {
            int pp = num[i];
            if (num[t] + r >= pp) {
                p = pp;
                i++;
                continue;
            }
            if (p + r < pp)
            {
                t = i;
                p = pp;
                sum++;
            }
            i++;
        }
        memset(num, 0, sizeof(num));
        printf("%d\n", sum);
    }
}

M-Cleaning Shifts

描述

大表哥分配 N (1 <= N <= 25,000) 只中的一些奶牛在牛棚附近做些清洁。 他总是要让至少一只牛做清洁。他把一天分成T段(1 <= T <= 1,000,000), 第一段是1,最后一段是T 

每只奶牛只在一些时间段有空。奶牛如果选择某一段时间,则必须完成整段时间的工作 

你的任务是帮助FJ安排一些奶牛,使每段时间至少有一只奶牛被安排来做这件事。并且奶牛数应尽可能小。如果不可能办到,输出-1

输入

注意,输入包含多组测试数据,请处理到文件结束
* 第一行:N和T 
* 第二行至N+1行: 每一行包括奶牛能工作的开始和结束时间。闭区间。

输出

*每组数据一行,输出完成清洁所需最少的奶牛数,如果不可能办到,输出-1

样例输入

3 10
1 7
3 6
6 10

样例输出

2
提示
这道题输入数据很多,请用scanf而不是cin 
输入说明 
这里有3只奶牛和10个时间段cow #1 能在时间段1..7工作, cow #2 能在时间段3..6工作, cow #3 能在时间段6..10工作 
输出说明: 选择 cows #1 和 #3即可,没有更优的方案了 .

  思路:仍旧采用贪心的解法 ,选取最优解。为了使用最小的牛覆盖所有时间段 ,就要使用开始的早,工作时间长的牛(具体实现使用cmp排序,优先级高的是开始时间,开始时间相同时比较结束时间,结束时间晚的优先);还要考虑一点即是所有牛的工作时间段

需要覆盖整个T时间段,中间不能有空缺(可以进行循环比较,当循环到某个牛该牛的工作开始时间比上一个工作的牛的结束时间相等或大于的时候,跳出循环)。代码如下:

#include <iostream>
#include <algorithm>
#define LL long long
int const max_n = 25100;
using namespace std;

struct node{
    int a,b;
}num[max_n];

bool cmp(node x,node y)//排序函数
{
    if(x.a==y.a)return x.b>y.b;
    else return x.a<y.a;
}

int main()
{
    int n,t;
    scanf("%d %d",&n,&t);
    for(int i=0;i<n;i++)
    {
        scanf("%d %d",&num[i].a,&num[i].b);
    }
    sort(num,num+n,cmp);
    int end=0,begin=0,sum=0;//结束时间,开始时间,计数器
    bool judge=false;
    for(int i=0;i<n;i++)
    {
        bool tt=false;//因为后面循环体内,在给结束时间赋值后,i又加了一次,所以跳出循环的i比实际牛的小标大一,在后面进行-1处理
        while(num[i].a<=begin+1&&i<n)//判断是否覆盖到了所有的时间段,如果中间出现时间断了的情况,则end值不会更新,导致begin值不会更新,每一个后来的牛的开始时间都将大于begin时间,这样在for循环内的if(begin>=t)不会执行,从而得出不能搬办到的结果。
        {
            tt=true;
            end=max(end,num[i].b);
            i++;
        }
        begin=end;
        sum++;
        if(tt)i--;
        if(begin>=t){
            judge=true;
            break;
        }
    }
    if(judge)printf("%d\n",sum);//只有工作时间覆盖所有时间段,且最后一头牛的结束时间大于总时间t时,输出使用的牛的数量
    else printf("-1\n");
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值