uva10148Advertisement(区间选点)

题目:uva10148Advertisement(区间选点)

题目大意:给出n个慢跑选手的慢跑区间,要求每个选手的区间至少要由k个广告,但是如果这个选手的慢跑区间长度放不下K个广告的话(特殊区间),那么就将这个选手的区间内都放满广告就可以了。问要满足上诉的要求,最少需要多少数量的广告,并且要找广告编号从小到大输出。

解题思路:区间选点问题。先将这些区间【a,b】按照b从小到大排序。如果b相同的话就按照a从大到小排序,这样保证前面的区间比后面的区间要小。每次选点的后都选靠近边界的点。这里要注意的是这里是要选K个点。但是这个区间内的可能会已经被前面的区间选了。所以这里要判断一下,这些点有没有被选。还需要判断这个区间是否是特殊的区间。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 1005;
const int M = 20005;

int k, n;
int visit[M];                                 //标记点选择状态

struct jogger {

	int a, b;
}jo[N];

int cmp (const jogger &a, const jogger &b) {

	if (a.b == b.b)
		return a.a > b.a;
	return a.b < b.b;
}

int solve () {

	int count = 0;
	int s = -M;
	int c;
	memset (visit, 0, sizeof (visit));
	for (int i = 0; i < n; i++) {

		if (jo[i].a > s) {                                                  //后一个区间和前一个区间没有重合

			//			printf ("%d\n", jo[i].b - jo[i].a + 1);
			if (jo[i].b - jo[i].a + 1 <= k) {                           //特殊的区间
				for (int j = jo[i].a; j <= jo[i].b; j++)
					visit[j + 10000] = 1;
				count += jo[i].b - jo[i].a + 1;
			} else {

				//				printf ("----\n");
				for (int j = jo[i].b; j > jo[i].b - k; j--)
					visit[j + 10000] = 1;
				count += k;
			}
			s = jo[i].b;
		} else {

			c = 0;                                           //由重合的话,需要统计一下这个区间已将选择的点的个数。
			for (int j = jo[i].a; j <= s; j++)
				if (visit[j + 10000])
					c++;

			if (jo[i].b - jo[i].a + 1 <= k) {                //特殊的区间

				if (c >= jo[i].b - jo[i].a + 1)
					continue;
				for (int j = jo[i].b; j >= jo[i].a; j--) {

					if (visit[j + 10000])
						continue;
					visit[j + 10000] = 1;
					count++;
				}
				s = jo[i].b;
			} else {

				if (c >= k)
					continue;
				int m = 0;
				for (int j = jo[i].b; j >= jo[i].a; j--) {

					if (m + c == k)
						break;
					if (visit[j + 10000])
						continue;
					visit[j + 10000] = 1;
					count++;
					m++;
				}
				s = jo[i].b;
			}
		}
	}
	return count;
}

int main () {

	int t;
	int a, b;
	scanf ("%d", &t);
	while (t--) {

		scanf ("%d%d", &k, &n);
		for (int i = 0; i < n; i++) {

			scanf ("%d%d", &a, &b);
			if (a < b) {
				jo[i].a = a;
				jo[i].b = b;
			} else {

				jo[i].a = b;
				jo[i].b = a;
			}
		}

		sort (jo, jo + n, cmp);
		int count = solve();
		printf ("%d\n", count);
		for (int i = 0; i < M; i++)
			if (visit[i])
				printf ("%d\n", i - 10000);
		if (t)
			printf ("\n");
	}
	return 0;
}

uva10148Advertisement(区间选点)

时间: 2024-08-25 17:14:57

uva10148Advertisement(区间选点)的相关文章

UVA10148- Advertisement(区间选点)

题意:一段路上,给出n个慢跑者跑步的区间,给出k,要求让每个慢跑者都能看到k个广告,区间都是整数操作,也就是说一个广告只能放在一个整数上,求最小贴的广告数 思路:关于区间选点的问题.把所有区间按B从小到大排序(B相同时A从大到小排序),则如果出现区间包含的情况,小区间一定排在前面.所以贪心的策略就是,从后往前取k个点.因为只有从后面开始取点,满足的区间才最会最多,这样就能达到使用最少的点的目的.注意如果区间长度小于k的话,区间内所有点都要取到. #include <iostream> #inc

区间选点+区间覆盖

区间选点+区间覆盖 区间选点问题(选择最少的点,使得每个区间都至少有k个点) 将这些区间[l,r]先按照r从小到大排序,再按照l从大到小排序.选点尽量选择靠近右边界的点.然后按照这个排序后的区间进行遍历,用一个变量来存放遍历过程中上个区间的右边界,然后碰到一个新的区间的时候需要分两种情况讨论:1.这个区间和上个区间有相交的部分,那么就需要判断一下上次选择的点有多少在这个区间内,这些点满足要求吗?不满足的话还需要在这个区间内选点2.这个区间和上个区间没有交集,那么这个区间就需要选点. 上述策略可以

poj1328Radar Installation(贪心—区间选点)

题目链接: 啊哈哈,点我点我 题目: Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 52037   Accepted: 11682 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small isl

HDU 4883 TIANKENG’s restaurant(区间选点)

HDU 4883 TIANKENG's restaurant 题目链接 题意:给定一些时间作为区间,和一个人数,问要安排多少人去看管(一个人只能看管一个人) 思路:普通的区间选点问题,一个区间拆成一个进入点一个出去点,然后排序循环求答案即可 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 20005; struct Man {

贪心--区间覆盖及区间选点问题

区间覆盖: 数轴上有若干区间,选用最少的线段覆盖指定区间. 区间选点:选用最少的区间使每个区间内至少有一个点 样题1: J - Muddy roads Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Description Farmer John has a problem: the dirt road from his farm to town has suffered in the re

UVa1615 Highway (贪心,区间选点)

链接:http://bak.vjudge.net/problem/UVA-1615 分析:以村庄为圆心,D为半径作圆,可选区间就是高速公路在圆内的部分(包括两个交点),按区间右端点从小到大,如若右端点相同再按左端点从大到小排好序,接下来就是很纯粹的区间选点问题. 1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 using namespace std; 5 6 const int maxn =

UVa 1615 Highway (贪心,区间选点问题)

题意:给定一个数 n 个点,和一个d,要求在x轴上选出尽量少的点,使得对于给定的每个点,都有一个选出的点离它的欧几里德距离不超过d. 析:首先这是一个贪心的题目,并且是区间选点问题,什么是区间选点呢,就是说在数轴上有 n 个闭区间,取尽量少的点,使得每个区间都至少有一个点. 一看是不是和这个题很相似,是的,那么区间哪里来呢?自己造呗,既然说是距离不超过d,意思就是在给定的点为圆心,以 d 为半径画圆,在x轴上的区间, 那么区间不就有了么,然后这个怎么贪心呢,是这样的,把所有的区间的右端点从小到大

Poj1328--Radar Installation(区间选点)

Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 64121   Accepted: 14418 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point loca

poj 1328 Radar Installation 【贪心】【区间选点问题】

Radar Installation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 54798   Accepted: 12352 Description Assume the coasting is an infinite straight line. Land is in one side of coasting, sea in the other. Each small island is a point loca