【动态规划】饥饿的奶牛

131 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

饥饿的奶牛

题目描述

有一条奶牛冲出了围栏,来到了一处圣地(对于奶牛来说),上面用牛语写着一段文字。

现用汉语翻译为:

NN 个区间,每个区间 x,yx,y 表示提供的 xyx\sim yyx+1y-x+1 堆优质牧草。你可以选择任意区间但不能有重复的部分。

对于奶牛来说,自然是吃的越多越好,然而奶牛智商有限,现在请你帮助他。

输入格式

第一行一个整数 NN

接下来 NN 行,每行两个数 x,yx,y,描述一个区间。

输出格式

输出最多能吃到的牧草堆数。

样例 #1

样例输入 #1

3
1 3
7 8
3 4

样例输出 #1

5

提示

1n1.5×1051 \leq n \leq 1.5 \times 10^50xy3×1060 \leq x \leq y \leq 3 \times 10^6

动态规划

首先不妨想象这些草地是一个一个的格子。

先从最简单的定义想起:

f[i]表示前 i 个格子最多能吃到多少牧草。

f[i]=max(f[i-1],f[j]+a[i].tail-a[i].head+1);//j表示尾小于当前区间头且f最大的区间下标

但是怎么对于所有的 j 都知道对应的所有的 i 呢?

发现一个 jj所对应的 i 的个数是不固定的,所以想到用 std::vector<int> 保存。

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
vector<int>beg[3000010];
int n,mx,f[3000010];//mx 代表最大的 y,f 就是 dp 用的数组
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		beg[y].push_back(x-1);//这里保存的是 x-1,后面会比较方便
		mx=max(mx,y);
	}
	for(int i=1;i<=mx;i++){
		f[i]=f[i-1];//先设定为 f[i-1],后面再更新
		for(int j=0;j<beg[i].size();j++){
			int b=beg[i][j];
			f[i]=max(f[i],f[b]+i-b);//这里会比较方便
		}
	}
	printf("%d\n",f[mx]);
	return 0;
}