题目要求如下:
要尽可能看更多的电视节目,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;
}
最后是通过后的结果:
通过逆序的方式很简单的解决了这个问题,而相比正序需要尝试的次数则要多很多。