uva 10148 - Advertisement

简介: 点击打开链接uva 101148 题目意思: 公园里有一个广告牌,由于公园里经常有很多人在慢跑锻炼身体,现在有一个客户想在这个广告牌上面贴广告,他想让每一个慢跑的人都能够看到至少k个广告,由于每一个人跑步的路径不同,不同人看到的广告是不同的,可能只看到一个广告。

点击打开链接uva 101148


题目意思:

公园里有一个广告牌,由于公园里经常有很多人在慢跑锻炼身体,现在有一个客户想在这个广告牌上面贴广告,他想让每一个慢跑的人都能够看到至少k个广告,由于每一个人跑步的路径不同,不同人看到的广告是不同的,可能只看到一个广告。现在规定广告是一序列连续的整数表示,有n个人,每一个能够看到的第一个广告和最后一个广告是已知的,现在要求满足这个客户的要求下(客户要求了要尽量省钱),找到最少需要贴广告的数量,并输出所贴的广告的编号 。


解题思路:

1思路:贪心

2分析:区间选点的变形题,由原来的选一个点变成现在选5个点,其它类似

3区间选点问题 :
       1解题过程:将每个线段按照终点坐标进行递增排序,相同终点的前点坐标大的在前面,一个个将其满足

       2贪心证明:要想使得剩下的线段上选择的点最少,那么就应该尽量使得已经选择了的点尽量能在后面的线段中发挥作用,而我们是从左往右选择线段的,那么要使得选取的点能满足后面线段的要求,那么必须是从线段的有端点开始选点,那么问题(2)一样涉及到一个问题,如果是按照线段的左端点对线段进行排序的话,不知道右端点的话,每一条线段都不能对之前已经操作过的所有线段进行一个总结,那么这就同样不满足贪心算法的最优子结构性质了

4解题过程:1首先对输入数据进行输出,让小的数据在第一个  2对这些区间按照Bi进行升序排序   3对这些区间进行扫描,假设当前的额区间为[Ai , Bi],那么我们必须先算出这个区间内的点出现过的个数num,如果num大于等于k那么之接跳过;否则还要在这个区间选取k-num个数,根据区间选点的性质则我们从Bi往前枚举如果当前的值为j没有被选那么就要选取这个点;依次直到枚举完所有的区间即可

5注意事项:用set来存储点,默认使用“<”进行排序。但是效率低,AC用了2.100s。


代码:

#include <algorithm>  
#include <iostream> 
#include <cstring>
#include <cstdio> 
#include <set>
using namespace std;
#define MAXN 1010

int t;
int k , n;
struct path{
    int first;
    int last;
}p[MAXN];
set<int>s;
/*自定义cmp函数*/
bool cmp(path p1 , path p2){
    if(p1.last < p2.last) return true;
    return false;
}

void solve() {
    int i , j , cnt;
    int num ,  tmp;
    ans = 0 ; s.clear() ;
    sort(p , p+n , cmp);/*快速排序*/
    set<int>::iterator it;
    for(i = 0 ; i < n ; i++){/*枚举n个区间*/
        num = 0;
        for(j = p[i].last ; j >= p[i].first ; j--){/*求出num*/
            it = s.find(j);
            if(it != s.end()) num++;
        }
        tmp = p[i].last - p[i].first + 1;
        if(num >= k || num == tmp) continue;/*num大于等于k跳过*/
        if(tmp > k) tmp = k;/*tmp为区间的长度,如果长度大于k则只要长度为k即可*/
        for(j = p[i].last , cnt = 0 ; cnt < tmp-num ; j--){/*从后往前推*/
            it = s.find(j);
            if(it == s.end()){
               s.insert(j) ; cnt++;
            }
        }
    }
}
/*输出set*/
void output(){
    printf("%d\n" , s.size());
    set<int>::iterator it;
    for(it = s.begin() ; it != s.end() ; it++)
        printf("%d\n" , *it);
}

int main() {
    //freopen("input.txt", "r", stdin);
    int a , b;
    scanf("%d%*c" , &t);
    while(t--){
         scanf("%d%d%*c" , &k , &n);       
         for(int i = 0 ; i < n ; i++){
             scanf("%d%d" , &a , &b);
             if(a < b){ p[i].first = a ; p[i].last = b; }
             else{ p[i].first = b ; p[i].last = a; }
         }
         solve() ; output();
         if(t) printf("\n");
    }
    return 0;
}



目录
相关文章
Uva10001 Garden of Eden
Uva10001 Garden of Eden
46 0
UVa10123 No Tipping
UVa10123 No Tipping
61 0
概率dp - UVA 11021 Tribles
Tribles  Problem's Link:  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33059   Mean:  有k个细菌,每个细菌只能存活一天,在死去之前可能会分裂出0,1,2....n-1个细菌,对应的概率为p0,p1,p2....pn-1。
827 0
uva 11806 - Cheerleaders
点击打开链接 题意:在一个n行m列的矩形里面放k个相同的石子,要求第一行,最后一行,第一列,最后一列都要有石子。问有几种方法? 思路: 1 如果题目没有要求“第一行,最后一行,第一列,最后一列都要有石子”,那么答案就是C[n*m][k],我们用C[i][j]表示i个里面选择j个的组合数。
819 0
|
机器学习/深度学习
uva 12470 Tribonacci
点击打开uva12470  思路: 矩阵快速幂 分析: 1 裸题 代码: /************************************************ * By: chenguolin ...
990 0
uva 10273 Eat or Not to Eat?
点击打开链接uva 10273 思路: 暴力求解 分析: 1 题目要求没有吃掉的奶牛的个数已经最后一次吃掉奶牛的天数 2 没有其它的方法只能暴力,对于n头牛的n个周期求最小公倍数,然后在2个公倍数之内暴力求解 代码: #inclu...
815 0