uva10148 - Advertisement(区间选点)

题意:
贴广告牌,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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值