poj 2373 灌溉草场【动态规划】- 难度★★★★★

Dividing the Path
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 5350 Accepted: 1872

Description

Farmer John's cows have discovered that the clover growing along the ridge of the hill in his field is particularly good. To keep the clover watered, Farmer John is installing water sprinklers along the ridge of the hill. 

To make installation easier, each sprinkler head must be installed along the ridge of the hill (which we can think of as a one-dimensional number line of length L (1 <= L <= 1,000,000); L is even). 

Each sprinkler waters the ground along the ridge for some distance in both directions. Each spray radius is an integer in the range A..B (1 <= A <= B <= 1000). Farmer John needs to water the entire ridge in a manner that covers each location on the ridge by exactly one sprinkler head. Furthermore, FJ will not water past the end of the ridge in either direction. 

Each of Farmer John's N (1 <= N <= 1000) cows has a range of clover that she particularly likes (these ranges might overlap). The ranges are defined by a closed interval (S,E). Each of the cow's preferred ranges must be watered by a single sprinkler, which might or might not spray beyond the given range. 

Find the minimum number of sprinklers required to water the entire ridge without overlap. 

Input

* Line 1: Two space-separated integers: N and L 

* Line 2: Two space-separated integers: A and B 

* Lines 3..N+2: Each line contains two integers, S and E (0 <= S < E <= L) specifying the start end location respectively of a range preferred by some cow. Locations are given as distance from the start of the ridge and so are in the range 0..L.

Output

* Line 1: The minimum number of sprinklers required. If it is not possible to design a sprinkler head configuration for Farmer John, output -1.

Sample Input

2 8
1 2
6 7
3 6

Sample Output

3

Hint

INPUT DETAILS: 

Two cows along a ridge of length 8. Sprinkler heads are available in integer spray radii in the range 1..2 (i.e., 1 or 2). One cow likes the range 3-6, and the other likes the range 6-7.

OUTPUT DETAILS: 

Three sprinklers are required: one at 1 with spray distance 1, and one at 4 with spray distance 2, and one at 7 with spray distance 1. The second sprinkler waters all the clover of the range like by the second cow (3-6). The last sprinkler waters all the clover of the range liked by the first cow (6-7). Here's a diagram: 
                 |-----c2----|-c1|       cows' preferred ranges

     |---1---|-------2-------|---3---|   sprinklers

     +---+---+---+---+---+---+---+---+

     0   1   2   3   4   5   6   7   8


The sprinklers are not considered to be overlapping at 2 and 6.

Source

USACO 2004 December Gold

题目大意:




郭炜老师的解题思路:



博主的代码(注释已经很详细了),参考郭炜老师的讲解

# include <iostream>
# include <cstring>
# include <queue>
# define INF 1<<31
# define MAXL 1000005   // 最大草场长度 
# define MAXN 1005		// 最大奶牛数  

using namespace std; 

int dp[MAXL];
int cowAt[MAXL];  // 判断当前点是否有奶牛存在 
int N, L, A, B;

struct Fx
{
	int x;
	int f; //喷头的数量
	bool operator <(const Fx & a) const {return f > a.f;} // 重构<符号,用于优先队列的排序 
	Fx(int xx = 0, int ff = 0):x(xx), f(ff){} // 构造函数 用来初始化x,f的值	
};
priority_queue<Fx> pqFx;  // 定义优先队列 

int main()
{
	cin >> N >> L;  // 输入奶牛的数量和草场的长度
	cin >> A >> B;  // 输入喷头的喷射半径范围[A, B]
	A <<= 1; B <<= 1; //把半径范围变成直径范围,方便计算
	memset(cowAt, 0, sizeof(cowAt));  // 初始化所有点都没有奶牛

/****************1*****************/ 
	// 这种存放奶牛的活动范围耗时长 250MS
//	for (int i = 0; i < N; i++)
//	{
//		int S, E; // 奶牛的活动范围(S, E)
//		cin >> S >> E;
//		for (int j = S+1; j < E; j++)  // 存放奶牛的活动范围  这种方法耗时长 
//		{
//			cowAt[j]++;
//		}
//	} 
//	
//	for (int i = 0; i <= L; i++)
//	{
//		dp[i] = INF; //先把所有的dp(x)初始化为无穷大
//	}
/****************1*****************/ 

/****************2*****************/ 
	// 这种耗时短	172MS 
	for (int i = 0; i < N; i++)
	{
		int S, E; // 奶牛的活动范围(S, E)
		cin >> S >> E;
		cowAt[S+1]++ ;
		cowAt[E]--;
	} 
	int inCow = 0; // 用来判断是否还在奶牛活动范围内
	for (int i = 0; i <= L; i++)
	{
		dp[i] = INF; //先把所有的dp(x)初始化为无穷大
		inCow += cowAt[i];  // 当cowAt[i] = 1, inCow = 1 直到cowAt[i] = -1, inCow = 0;
		cowAt[i] = (inCow > 0); // 把有奶牛存在的点变为1; 
	}
/****************2*****************/ 	
// 两种方法耗时相差不大
 
	for (int i = A; i <= B; i += 2) 
	{
		if (!cowAt[i])  // 如果当前点没有奶牛,则说明此点有可能放置一个喷头 
		{
			dp[i] = 1;   // 把当前的喷头数初始化为1  
			if (i <= B + 2 - A) // 如果下一个x点符合(b+2-a),即下一点有可能放置喷头 
			{
				pqFx.push(Fx(i, 1));   
			}
		}
	}
	for (int i = B + 2; i <= L; i += 2)
	{
		if (!cowAt[i])
		{
			Fx fx;
			while (!pqFx.empty())
			{
				fx = pqFx.top();
				if (fx.x < i - B) //当前点不符合放置喷头 
				{
					pqFx.pop(); 
				}
				else 
				{
					break;
				}
			}
			if (!pqFx.empty())
			{
				dp[i] = fx.f + 1;
			}
		}
		if (dp[i-A+2] != INF) // 如果下一点可到达 
		{
			pqFx.push(Fx(i-A+2, dp[i-A+2]));  // 存放下一个x点 
		}	
	}
	if (INF == dp[L]) 
	{
		cout << -1 << endl;
	}
	else 
	{
		cout << dp[L] << endl;
	}
	return 0;
}

别人家的博主的Ac代码(短小精悍)http://lgs-oi.blog.163.com/blog/static/231255002201422592916209/

#include<cstdio>
#define maxl 1000003
#define maxn 2000
#define maxx 99999999
using namespace std;
int h,t,i,j,n,k,m,tem,l,q,p;
int f[maxl],w[maxl],queue[maxl];
bool b[maxl];
struct node{
       int l,r;
}a[maxn];
int main()
{
	scanf("%d%d",&n,&l);
	scanf("%d%d",&q,&p);
	for (i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
	    if (a[i].r-a[i].l>2*p) 
		{
	      	printf("-1");
	      	return 0;
		}
		for (j=a[i].l+1;j<=a[i].r-1;j++) 
			b[j]=true;
	}
	for (i=1;i<=l;i++) 
		f[i]=maxx;
	h=1;t=1;
	for (i=2*q;i<=l;i++)
	{
        tem=i-2*q;
        while (t>h&&queue[t-1]>=f[tem])
			t--;
        if (!b[tem]) 
		{
			queue[t]=f[tem];w[t]=tem;t++;
		}
        if ((i%2==1)||(b[i]))  
			continue;
	    while (t>h&&w[h]+2*p<i)
			h++;
	    if (t>h) 
			f[i]=queue[h]+1;
    }
	if (f[l]>=maxx)
		printf("-1");
	else 
		printf("%d",f[l]);
	return 0;
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值