饥饿的牛 线性dp内的区间

饥饿的牛

牛在饲料槽前排好了队。饲料槽依次用1到N(1<=N<=100000)编号。每天晚上,一头幸运的牛根据约翰的规则,吃其中一些槽里的饲料。

约翰提供B个区间的清单。一个区间是一对整数start-end,1<=start<=end<=N,表示一些连续的饲料槽,比如1-3,7-8,3-4等等。牛可以任意选择区间,但是牛选择的区间不能有重叠。
当然,牛希望自己能够吃得越多越好。给出一些区间,帮助这只牛找一些区间,使它能吃到最多的东西。
在上面的例子中,1-3和3-4是重叠的;聪明的牛选择{1-3,7-8},这样可以吃到5个槽里的东西。

输入
第一行,整数B(1<=B<2000)
第2到B+1行,每行两个整数,表示一个区间,较小的端点在前面。

输出
仅一个整数,表示最多能吃到多少个槽里的食物。

样例
输入:
3
1 3
7 8
3 4
输出:
5
说明:数据前10组为小数据,后10组为大数据,N〈=10000000;B〈=100000

然后那到这道题就有两个想法

1.设f(i)为到前i个点能得到的最大区间

{

  如果没有到i的区间f(i)=f(i-1);

  否则f(i)=f(所有到i的开始位置的点-1)+区间和;

  f(i)=max(f(i-1),f(i));

}
然后用链表优化时间

#include<cstdio>
#include<algorithm>
#define N1 100000+1
#define N2 2000+1
using namespace std;
struct edge{
    int next;
    int to;
};
int num,head[N1];
edge e[N2];
void add(int from,int to)
{
    e[++num].next=head[from];
    e[num].to=to;
    head[from]=num;
}
int f[N1];
bool flag[N1];
int main()
{
    int b,x,y,n=0;
    scanf("%d",&b);
    for(int i = 1;i<=b;i++)
    {
        scanf("%d%d",&x,&y);
        add(y,x);
        if(y>n)n=y;
        flag[y]=1;
    }
    for(int i=1;i<=n;i++)
    {
        f[i]=f[i-1];
        if(!flag[i])continue;
        else{
            for(int j=head[i];j;j=e[j].next)
            {
                int v=e[j].to;
                f[i]=max(f[i],f[v-1]+(i-v+1));
            }
        }
    }
    printf("%d",f[n]);
    return 0;
}

2.设f(i)为前i个区间能获得的最大区间值

貌似要以区间右端点排序

1.f(i)=f(i-1)

2.f(i)=f(不在这个区间内,却最靠近这个区间的左断点)+这个区间的值

f(i)=max{1,2};

时间复杂度O(nlogn);

空间复杂度O(n);

因为排序,所以可以用二分查找优化,否则超时

#include<cstdio>
#define maxn 100000+2
using namespace std;
int f[maxn],b;
struct s_p
{
	int s,e;
	bool operator <(s_p b)
	{
		return s<b.s;
	}
}data[maxn];
void change(s_p &a,s_p &b)
{
	s_p t=a;a=b;b=t;
}
void sort(int a,int b)
{
	if(a==b)return;
	s_p val=data[(a+b)/2];
	int i=a-1,j=b+1;
	while(1)
	{
	  do i++;while(data[i]<val);
	  do j--;while(val<data[j]);
	  if(i>=j)break;
	  change(data[i],data[j]);
    }
    sort(a,j);
    sort(j+1,b);
}
int find(int a,int B,int c)
{
	if(a==B)
	{
		if(data[a].s>=c)return a;
		return b+1;
	}
	int mid=(a+B)/2;
	if(c<=data[mid].s)return find(a,mid,c);
	return find(mid+1,B,c);
}
int main()
{
//	freopen("10034.in","r",stdin);
//	freopen("10034.out","w",stdout);
	scanf("%d",&b);
	for(int i=1;i<=b;i++)
	scanf("%d%d",&data[i].s,&data[i].e);
	sort(1,b);
	for(int i=b;i>=1;i--)
	{
		f[i]=f[i+1];
		int t=find(1,b,data[i].e+1);
		if(f[i]<f[t]+data[i].e-data[i].s+1)f[i]=f[t]+data[i].e-data[i].s+1;
	}
	printf("%d",f[1]);
	fclose(stdout);
	return 0;
}

  

时间: 2024-12-15 07:00:02

饥饿的牛 线性dp内的区间的相关文章

LightOJ1044 Palindrome Partitioning(区间DP+线性DP)

问题问的是最少可以把一个字符串分成几段,使每段都是回文串. 一开始想直接区间DP,dp[i][j]表示子串[i,j]的答案,不过字符串长度1000,100W个状态,一个状态从多个状态转移来的,转移的时候要枚举,这样时间复杂度是不可行的. 然后我就想降维度了,只能线性DP,dp[i]表示子串[0,i]的答案.这样可以从i-1转移到i,str[i]单独作一段或者str[i]能和前面的组成回文串,方程如下: dp[i]=min(dp[i-1]+1,dp[j-1]+1) (子串[j,i]是回文串) 现在

【动态规划】饥饿的牛- 10034

[动态规划]饥饿的牛- 10034 Time Limit: 1000MS Memory Limit: 32768KB 牛在饲料槽前排好了队.饲料槽依次用1到N(1<=N<=100000)编号.每天晚上,一头幸运的牛根据约翰的规则,吃其中一些槽里的饲料.   约翰提供B个区间的清单.一个区间是一对整数start-end,1<=start<=end<=N,表示一些连续的饲料槽,比如1-3,7-8,3-4等等.牛可以任意选择区间,但是牛选择的区间不能有重叠. 当然,牛希望自己能够吃

动态规划——线性dp

我们在解决一些线性区间上的最优化问题的时候,往往也能够利用到动态规划的思想,这种问题可以叫做线性dp.在这篇文章中,我们将讨论有关线性dp的一些问题. 在有关线性dp问题中,有着几个比较经典而基础的模型,例如最长上升子序列(LIS).最长公共子序列(LCS).最大子序列和等,那么首先我们从这几个经典的问题出发开始对线性dp的探索. 首先我们来看最长上升子序列问题. 这个问题基于这样一个背景,对于含有n个元素的集合S = {a1.a2.a3……an},对于S的一个子序列S‘ = {ai,aj,ak

uva 11584 Partitioning by Palindromes 线性dp

// uva 11584 Partitioning by Palindromes 线性dp // // 题目意思是将一个字符串划分成尽量少的回文串 // // f[i]表示前i个字符能化成最少的回文串的数目 // // f[i] = min(f[i],f[j-1] + 1(j到i是回文串)) // // 这道题还是挺简单的,继续练 #include <algorithm> #include <bitset> #include <cassert> #include <

uva 11552 Fewest Flops 线性dp

// uva 11552 Fewest Flops // // 二维线性dp // // 首先,在该块必须是相同的来信.首先记录每块有很多种书 // 称为是counts[i]; // // 订购f[i][j]它代表前i字母j为结尾的最小分块数 // // 假设第i块的開始字母与第i-1块的结束字母同样 // f[i][j] = min(f[i][j],f[i-1][k] + counts[i] - 1); // // 否则 // // f[i][j] = min(f[i][j],f[i-1][k

poj3267——线性dp

poj3267——线性dp The Cow Lexicon Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8458   Accepted: 3993 Description Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, each containing no more 25 of the characters 'a'

线性DP POJ2279 Mr.Young&#39;s Picture Permutations

Mr. Young's Picture Permutations Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1128   Accepted: 562 Description Mr. Young wishes to take a picture of his class. The students will stand in rows with each row no longer than the row behin

HDU 5074 Hatsune Miku (线性dp)

Hatsune Miku Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 654    Accepted Submission(s): 471 Problem Description Hatsune Miku is a popular virtual singer. It is very popular in both Japan

Codeforces 176B (线性DP+字符串)

题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=28214 题目大意:源串有如下变形:每次将串切为两半,位置颠倒形成新串.问经过K次变形后,与目标串相同的变形方案数.mod 1000000007. 解题思路: 奇葩的字符串DP.照着别人的题解写的,解释不出原理是什么. 首先统计出经过1次变形,就能和目标串相同的中间产物串(包含源串)的个数cnt.len表示源串长度,那么len-cnt就表示和目标串不同的个数. 用