Codeup[100000584]看电视

题目要求如下:
在这里插入图片描述要尽可能看更多的电视节目,1种解决方式是,先找到开始时间最早的节目,然后依次搜索是否查看其最大能查看的节目数量。
此时,可以使用递归依次进行,对应的实现代码如下:

#include <stdio.h>
#include <stdlib.h>
int max_value = 0;

int int_compare(const void *p1, const void *p2) {
    int *a = (int *) p1;
    int *b = (int *) p2;
    if(a[0]!=b[0]){
        return a[0] - b[0];
    } else{
        return a[1] - b[1];
    }
}

int find_max(int (*remain)[2], int n, int len, int score) {
    for (int i = n; i < len; ++i) {
        int a = remain[i][0] + remain[i][1];
        for (int j = n+1; j < len; ++j) {
            if (a <= remain[j][0]) {
                // 结束时间小于下1个节目的开始时间,进行下1个节目的搜索
                find_max(remain, j, len, score+1);
            }
        }
    }
    if (score > max_value) {
        max_value = score;
    }
    return score;
}

int main(int argc, char const *argv[]) {
    int n;
    int arr[101][2] = {0};
    int remain[101][2] = {0};
    while(scanf("%d",&n)!=EOF){
        if(n==0){
            break;
        }
        for (int i = 0; i < n; ++i) {
            scanf("%d%d",&arr[i][0],&arr[i][1]);
        }
        for (int j = 0; j < n; ++j) {
            int *a = arr[j];
            remain[j][0] = a[0];
            remain[j][1] = a[1] - a[0];
        }
        qsort(remain, n, sizeof(remain[0]), int_compare);
        find_max(remain, 0, n, 0);
        printf("%d\n", max_value+1);
    }
    return 0;
}

我们从第1个最早的节目开始,当第1个节目时查找下1个开始时间等于或大于第1个节目结束时间的节目。以此类推,直到所有节目都进行一遍。
但是使用递归的方式不好的地方在于需要花费的时间非常长,对于100个节目的搜索,其搜索次数最坏情况为100!,很容易造成执行时间超时。
其结果如下:
在这里插入图片描述
可以看到花费了近3秒才执行完成。

另1个可行的方式将节目按照结束时间进行排序,当开始时间相同时首先寻找结束时间最大的,而当开始时间不同时寻找开始时间最小的。
接着按照逆序进行搜索,当最后1个节目开始往前搜索前1个结束时间小于当前节目的,将其开始时间设置为结束时间。
比如有5个节目:

开始时间  结束时间
1               5
3               5
2               3
6               8
7               9

那么先进行排序后,假设从开始时间为7,结束时间为9的节目开始,往前可以选择开始时间为3,结束时间为5的节目,由于开始时间6而结束时间为8的节目与最后1个节目冲突,因此不进行选择。以此类推,从而可以观察3个节目。
因此,对应实现的代码如下:

#include <stdio.h>
#include <stdlib.h>


int int_compare(const void *p1, const void *p2) {
    int *a = (int *) p1;
    int *b = (int *) p2;
    // 开始时间不同,开始时间晚的在前
    if (a[0] != b[0]) {
        return b[0] - a[0];
    } else {
    // 开始时间相同,结束时间晚的在前
        return b[1] - a[1];
    }
}

int find_max(int (*remain)[2], int n, int len) {
    int score = 1;
    int start = remain[0][0];
    for (int j = n + 1; j < len; ++j) {
        // 最晚节目的开始时间要比下1个节目结束时间要早
        if (start >= remain[j][1]) {
            score++;
            // 下1个节目的开始时间比下下1个节目结束时间要早
            start = remain[j][0];
        }
    }
    return score;
}

int main(int argc, char const *argv[]) {
    int n;
    int arr[101][2] = {0};
    int remain[101][2] = {0};
    while (scanf("%d", &n) != EOF) {
        if (n == 0) {
            break;
        }
        for (int i = 0; i < n; ++i) {
            scanf("%d%d", &arr[i][0], &arr[i][1]);
        }
        // 排序
        qsort(arr, n, sizeof(arr[0]), int_compare);
        int score = find_max(arr, 0, n);
        printf("%d\n", score);
    }
    return 0;
}

最后是通过后的结果:
在这里插入图片描述
通过逆序的方式很简单的解决了这个问题,而相比正序需要尝试的次数则要多很多。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值