CODE[VS] 3027 线段覆盖 2

题目描述 Description

数轴上有n条线段,线段的两端都是整数坐标,坐标范围在0~1000000,每条线段有一个价值,请从n条线段中挑出若干条线段,使得这些线段两两不覆盖(端点可以重合)且线段价值之和最大。

n<=1000

输入描述 Input Description

第一行一个整数n,表示有多少条线段。

接下来n行每行三个整数, ai bi ci,分别代表第i条线段的左端点ai,右端点bi(保证左端点<右端点)和价值ci。

输出描述 Output Description

输出能够获得的最大价值

样例输入 Sample Input

3

1 2 1

2 3 2

1 3 4

样例输出 Sample Output

4

数据范围及提示 Data Size & Hint

数据范围

对于40%的数据,n10

对于100%的数据,n1000

0<=ai,bi<=1000000

0<=ci<=1000000



记得做过一个类似的贪心的题目,那个只要根据结尾点排序,然后进行贪心即可。这个题略有不同,因为涉及到价值的存在,我们用动态规划来做
我们还是按照结尾点排序,然后从左向右遍历。用双重循环的形式,外层循环是大的遍历整个数组,内层循环是遍历当前所在的数组位置的前面的单元,找到一个最大的且不与当前位置重合的单元,将其价值加到当前位置上。

代码如下:
/*************************************************************************
    > File Name: 线段覆盖2.cpp
    > Author: zhanghaoran
    > Mail: chilumanxi@gmail.com 
    > Created Time: 2015年07月19日 星期日 08时33分53秒
 ************************************************************************/

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

using namespace std;

int n;
struct  node{
	int s;
	int e;
	int v;
}q[1001];

int dp[1000];
int ans = 0;

int cmp(const node x, const node y){
	return x.e < y.e;
}
int main(void){
	cin >> n;
	for(int i = 0; i < n; i ++){
		cin >> q[i].s >> q[i].e >> q[i].v;
	}
	sort(q, q + n, cmp);
	int ans  = 0;
	for(int i = 1; i < n; i ++){
		int temp = 0;
		for(int j = 0; j < i; j ++){
			if(q[i].s >= q[j].e){
				if(temp < q[j].v)
					temp = q[j].v;
			}
		}
		q[i].v = q[i].v + temp;
		if(ans < q[i].v){
			ans = q[i].v;
		}
	}
	cout << ans << endl;
	return 0;
}


原文地址:https://www.cnblogs.com/chilumanxi/p/5136111.html