uva 10148 Advertisement

原题:
The Department of Recreation has decided that it must be more profitable, and it wants to sell advertising space along a popular jogging path at a local park. They have built a number of billboards (special signs for advertisements) along the path and have decided to sell advertising space on these billboards. Billboards are situated evenly along the jogging path, and they are given consecutive integer numbers corresponding to their order along the path. At most one advertisement can be placed on
each billboard. A particular client wishes to purchase advertising space on these billboards but needs guarantees
that every jogger will see it’s advertisement at least K times while running along the path. However, different joggers run along different parts of the path. Interviews with joggers revealed that each of them has chosen a section of the path which he/she
likes to run along every day. Since advertisers care only about billboards seen by joggers, each jogger’s personal path can be identified by the sequence of billboards viewed during a run. Taking into account that billboards are numbered consecutively, it is sufficient to record the first and the last billboard numbers seen by each jogger.
Unfortunately, interviews with joggers also showed that some joggers don’t run far enough to see K billboards. Some of them are in such bad shape that they get to see only one billboard (here, the first and last billboard numbers for their path will be identical). Since out-of-shape joggers won’t get to see K billboards, the client requires that they see an advertisement on every billboard along their section of the path. Although this is not as good as them seeing K advertisements, this is the best that can
be done and it’s enough to satisfy the client. In order to reduce advertising costs, the client hires you to figure out how to minimize the number of billboards they need to pay for and, at the same time, satisfy stated requirements.
Input
The first line of the input consist of an integer indicating the number of test cases in theinput. Then
there’s a blank line and the test cases separated by a blank line.
The first line of each test case contains two integers K and N (1 ≤ K,N ≤ 1000) separated by
a space. K is the minimal number of advertisements that every jogger must see, and N is the total
number of joggers.
The following N lines describe the path of each jogger. Each line contains two integers A i and B i
(both numbers are not greater than 10000 by absolute value). A i represents the first billboard number
seen by jogger number i and B i gives the last billboard number seen by that jogger. During a run,
jogger i will see billboards A i , B i and all billboards between them.
Output
On the first line of the output for each test case, write a single integer M. This number gives the
minimal number of advertisements that should be placed on billboards in order to fulfill the client’s
requirements. Then write M lines with one number on each line. These numbers give (in ascending
order) the billboard numbers on which the client’s advertisements should be placed.
Print a blank line between test cases.
Sample Input
1
5 10
1 10
20 27
0 -3
15 15
8 2
7 30
-1 -10
27 20
2 9
14 21
Sample Output
19
-5
-4
-3
-2
-1
0
4
5
6
7
8
15
18
19
20
21
25
26
27

中文:
给你一个一维数轴,然后给你一堆区间,现在让你在区间里面找最少的点,使得每个区间当中至少有k个点,区间长度小于k的,那么选择所有区间中的点。
最后输出点的数量和所有点。


代码:

#include<bits/stdc++.h>
using namespace std;
int n, k;
struct section
{
    int a, b;
    bool operator<(const section &s) const
    {
        return b<s.b;
    }
    int num = 0;
};

vector<section> sec;
vector<int> has[20001];//
bool mark[20001];
set<section> uss;
vector<int> ans;

int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--)
    {
        cin >> k >> n;
        int a, b, l = INT_MAX, r = INT_MIN;
        for (int i = 0; i <= 20000; i++)
            has[i].clear();
        uss.clear();
        sec.clear();
        ans.clear();
        section tmp;
        memset(mark,false,sizeof(mark));
        for (int i = 1; i <= n; i++)
        {
            cin >> a >> b;
            a += 10000;
            b += 10000;
            if (a>b)
                swap(a, b);
            tmp.a = a;
            tmp.b = b;
            tmp.num = 0;
            sec.push_back(tmp);
        }

        sort(sec.begin(),sec.end());
        for(int i=0;i<sec.size();i++)
        {
            for (int j = sec[i].a; j <= sec[i].b; j++)
            {
                has[j].push_back(i);
            }
        }
        for(int i=0;i<sec.size();i++)
        {
            if(sec[i].num>=k)
                continue;

            int cnt=sec[i].num;
            for(int j=sec[i].b;j>=sec[i].a;j--)
            {
                if(cnt>=k)
                    break;

                if(!mark[j])
                {
                    mark[j]=1;
                    cnt++;
                    ans.push_back(j);
                    for(auto y:has[j])
                    {
                        sec[y].num++;
                    }
                }
            }
        }
        cout<<ans.size()<<endl;
        sort(ans.begin(),ans.end());
        for(int i=0;i<ans.size();i++)
            cout<<ans[i]-10000<<endl;
        if(t)
            cout<<endl;
    }
    return 0;
}


解答:

算法入门经典在贪心一章里面有此题的讲解,思路为先将区间按照右端点从小到大排序,然后再区间中选点,这样做是正确的原因是,如果大的区间包含小的区间,那么小区间的右端点一定是小于或者等于大区间,所以首先选择到的区间一定是区间长度最小的。
然后,枚举区间,每次选择区间中的点时从右向左选择,这样做可以使当前选择到的点尽量多的在多个区间当中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值