POJ3171 Cleaning Shifts DP,区间覆盖最值

题目大意,N个区间覆盖[T1,T2]及对应的代价S,求从区间M到E的全部覆盖的最小代价是多少。 (1 <= N <= 10,000),(0 <= M <= E <= 86,399).

思路是DP,首先将每个区间按照T2从小到大排序,设dp(k)为从m覆盖到k所需最小代价,则有

dp(T2[i]) = min(dp(T2[i]), {dp(j) + Si,  T1[i] - 1<=j <= T2[i]}),对于 {dp(j)
+ Si,  T1[i] - 1<=j <= T2[i]}我们可以用线段树来进行优化,所以最终复杂度为O(n*logE)。

#include <stdio.h>
#include <vector>
#include <math.h>
#include <string.h>
#include <string>
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <stack>
#include <map>
#include <time.h>
using namespace std;

struct T
{
	int t1;
	int t2;
	int S;
};
#define MAXV 5000000001
long long BinTree[270000];
T cows[10001];
long long DP[86401];

template<class TYPE>
void UpdateValue(TYPE st[],int i, TYPE value, int N, bool bMin)
{
	i += N - 1;
	st[i] = value;
	while (i > 0)
	{
		i = (i - 1) / 2;
		if (bMin)
		{
			st[i] = min(st[i * 2 + 1], st[i * 2 + 2]);
		}
		else
			st[i] = max(st[i * 2 + 1], st[i * 2 + 2]);
	}
}

template<class TYPE>
TYPE QueryST(TYPE st[], int a, int b, int l, int r, int k, bool bMin)
{
	if (l > b || a > r)
	{
		return bMin ? MAXV : 0;
	}
	if (l >= a && b >= r)
	{
		return st[k];
	}
	else
	{
		TYPE value1 = QueryST(st, a, b, l, (r + l) / 2, k * 2 + 1, bMin);
		TYPE value2 = QueryST(st, a, b, (r + l) / 2 + 1, r, k * 2 + 2, bMin);
		if (bMin)
		{
			return min(value1, value2);
		}
		else
		{
			return max(value1, value2);
		}
	}
}

int compT(const void* a1, const void* a2)
{
	if (((T*)a1)->t2 - ((T*)a2)->t2 == 0)
	{
		return ((T*)a1)->t1 - ((T*)a2)->t1;
	}
	else
		return ((T*)a1)->t2 - ((T*)a2)->t2;
}

int main()
{
#ifdef _DEBUG
	freopen("e:\\in.txt", "r", stdin);
#endif
	int N, M, E;
	scanf("%d %d %d", &N, &M, &E);
	M++;
	E++;
	for (int i = 0; i < N; i++)
	{
		scanf("%d %d %d", &cows[i].t1, &cows[i].t2, &cows[i].S);
		cows[i].t1++;
		cows[i].t2++;
	}
	int maxe = 1;
	while (maxe < E)
	{
		maxe *= 2;
	}
	for (int i = 0; i < maxe * 2;i++)
	{
		BinTree[i] = MAXV;
	}
	for (int i = 0; i <= E;i++)
	{
		DP[i] = MAXV;
	}

	DP[M - 1] = 0;
	UpdateValue<long long>(BinTree, M - 1, 0, maxe, true);
	qsort(cows, N, sizeof(T), compT);
	for (int i = 0; i < N;i++)
	{
		DP[cows[i].t2] = min(DP[cows[i].t2], QueryST<long long>(BinTree, cows[i].t1 - 1, cows[i].t2, 0, maxe - 1, 0, true) + cows[i].S);
		UpdateValue<long long>(BinTree, cows[i].t2, DP[cows[i].t2], maxe, true);
	}
	if (E <= cows[N - 1].t2)
	{
		DP[E] = QueryST<long long>(BinTree, E, cows[N - 1].t2, 0, maxe - 1, 0, true);
	}

	if (DP[E] >= MAXV)
	{
		printf("-1\n");
	}
	else
		printf("%I64d\n", DP[E]);
	return 0;
}

POJ3171 Cleaning Shifts DP,区间覆盖最值,布布扣,bubuko.com

时间: 2025-01-02 19:15:13

POJ3171 Cleaning Shifts DP,区间覆盖最值的相关文章

poj3171 Cleaning Shifts【线段树(单点修改区间查询)】【DP】

Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4422   Accepted: 1482 Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer

POJ3171——Cleaning Shifts

Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2813   Accepted: 976 Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer J

HDU5900-QSC and Master-区间DP+区间覆盖DP

地址 http://acm.hdu.edu.cn/showproblem.php?pid=5900 2016ICPC沈阳赛区网络赛 题意:一个队列,每个点有key[i]和value[i],位置相邻且key不互质的两个点可以被取走,取走后,剩下点自动连接起来. 问取走的value和最大 题解:1.对于所有的区间,用区间DP求出能否 整个 区间取走 枚举区间长度 对于[s,e] 的区间,要么由两个比这短的区间拼凑而成,要么s和e可以不互质,且[s+1,e-1]可以取走,特判长度为2的时候. 2.对于

[POJ3171] Cleaning Shifts

题意:FJ有一段时间[S,T]需要奶牛们打扫卫生,他有N头牛,每头牛可以在[si,ti]打扫卫生,但需要付vi元钱,求[S,T]每时每刻都有牛打扫卫生的最小代价 题解: spfa(最短路转化) [si,ti]打扫卫生相当于从si连一条边到ti+1,连完所有的牛之后,还要添加回溯路径,最后一遍spfa即可 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #inclu

poj2376 Cleaning Shifts(区间贪心,理解题意)

https://vjudge.net/problem/POJ-2376 题意理解错了!!真是要仔细看题啊!! 看了poj的discuss才发现,如果前一头牛截止到3,那么下一头牛可以从4开始!!! 1 #include<iostream> 2 #include<cstdio> 3 #include<queue> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7

POJ - 2376 Cleaning Shifts 贪心(最小区间覆盖)

Cleaning Shifts Farmer John is assigning some of his N (1 <= N <= 25,000) cows to do some cleaning chores around the barn. He always wants to have one cow working on cleaning things up and has divided the day into T shifts (1 <= T <= 1,000,000

POJ 2376 Cleaning Shifts (贪心,区间覆盖)

题意:给定1-m的区间,然后给定n个小区间,用最少的小区间去覆盖1-m的区间,覆盖不了,输出-1. 析:一看就知道是贪心算法的区间覆盖,主要贪心策略是把左端点排序,如果左端点大于1无解,然后, 忽略小于1的部分(如果有的话),再找最长的区间,然后把这个区间的右端点作为下次寻找的起点, 再找最大区间,直到覆盖到最后. 注意:首先要判断好能不能覆盖,不能覆盖就结束,有可能会提前结束,也要做好判断,我就在这WA了好几次, 悲剧...其他的就比较简单了,不用说了. 代码如下: #include <ios

poj 3171 Cleaning Shifts(区间的最小覆盖价值)

Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2743   Accepted: 955 Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer J

算法模板——线段树3(区间覆盖值+区间求和)

实现功能——1:区间覆盖值:2:区间求和 相比直接的区间加,这个要注重顺序,因为操作有顺序之分.所以这里面的tag应该有个pushup操作(本程序中的ext) 1 var 2 i,j,k,l,m,n,a1,a2,a3,a4:longint; 3 a,b,d:array[0..100000] of longint; 4 function max(x,y:longint):longint;inline; 5 begin 6 if x>y then max:=x else max:=y; 7 end;