题意:
贴广告牌,n个人,会分别在一个区间内跑步,区间点为整数,在这些整数里,你负责选点贴广告,让他们每个人都至少能看见K个广告,若区间范围小于k,则该区间都要贴广告
思路:
贪心题。参考了《算法经典入门》中做法,首先区间左小右大,然后按右边界排序,尽量多得在右边放广告牌,因为这样的话重叠部分小,所需放置的广告牌亦随之变小。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1005;
struct run{
int s, e;
}a[N];
int n,k;
int vis[N+20000];
int cmp(run x, run y) {
return x.e < y.e;
}
int main() {
int cas;
scanf("%d", &cas);
while (cas--) {
scanf("%d%d", &k, &n);
int ss, ee;
for (int i = 0; i < n; i++) {
scanf("%d%d", &ss, &ee);
if (ss > ee) {
int t = ss;
ss = ee;
ee = t;
}
a[i].s = ss+10000;
a[i].e = ee+10000;
}
sort(a, a + n, cmp);
memset(vis, 0, sizeof(vis));
int sum = 0;
for (int i = 0; i < n; i++) {
int cnt = 0;
if (a[i].e - a[i].s +1 <= k) {
for (int j = a[i].s; j <= a[i].e; j++) {
if (!vis[j]) {
vis[j] = 1;
sum++;
}
}
}
else {
for (int j = a[i].s; j <= a[i].e; j++)
if (vis[j])
cnt++;
if (cnt >= k)
continue;
for (int j = a[i].e; j >= a[i].s; j--){
if (!vis[j]) {
vis[j] = 1;
cnt++;
sum++;
if (cnt >= k)
break;
}
}
}
}
printf("%d\n", sum);
for (int i = 0; i < N+20000; i++) {
if (vis[i])
printf("%d\n", i-10000);
}
if (cas)
printf("\n");
}
return 0;
}