【C++】Cut the Sequence

【来源】

POJ-3017
vjudge

【题目描述】

Given an integer sequence { an } of length N, you are to cut the sequence into several parts every one of which is a consecutive subsequence of the original sequence. Every part must satisfy that the sum of the integers in the part is not greater than a given integer M. You are to find a cutting that minimizes the sum of the maximum integer of each part.

【输入格式】

The first line of input contains two integer N (0 < N ≤ 100 000), M. The following line contains N integers describes the integer sequence. Every integer in the sequence is between 0 and 1 000 000 inclusively.

【输出格式】

Output one integer which is the minimum sum of the maximum integer of each part. If no such cuttings exist, output −1.

【样例输出】

8 17
2 2 2 8 1 8 2 1

【样例输出】

12

【数据范围】

Use 64-bit integer type to hold M.

【题目大意】

给定一个长度为N的序列,你需要把序列分成很多段。每段的和不能超过M。每段的价值为这段的最大值。如何分割使得所有段的价值总和最小。

【解析】

单调队列优化动态规划。
转移方程:
d p [ i ] = m i n { d p [ j ] + m a x a [ j + 1 ] , a [ j + 2 ] . . . a [ i ] } dp[i] = min \{ dp[j] + max{a[j+1], a[j+2] ... a[i]} \} dp[i]=min{ dp[j]+maxa[j+1],a[j+2]...a[i]}
d p [ j − 1 ] + m a x { a [ j ] . . . a [ i − 1 ] } = = d p [ j − 1 ] + m a x { a [ j ] . . . a [ i ] } dp[j-1] + max\{a[j] ... a[i-1]\} == dp[j-1] + max\{a[j] ... a[i]\} dp[j1]+max{ a[j]...a[i1]}==dp[j1]+max{ a[j]...a[i]}

扫描二维码关注公众号,回复: 11650296 查看本文章

【代码】

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

#define RI                 register int
#define re(i,a,b)          for(RI i=a; i<=b; i++)
#define ms(i,a)            memset(a,i,sizeof(a))
#define MAX(a,b)           (((a)>(b)) ? (a):(b))
#define MIN(a,b)           (((a)<(b)) ? (a):(b))

using namespace std;

typedef long long LL;

const int N=1e5+5;
const int inf=1e9;

LL n,m;
LL a[N],dp[N],q[N];

int main() {
    
    
	int flag=1;
	scanf("%lld%lld",&n,&m);
	for(int i=1; i<=n; i++) {
    
    
		scanf("%lld",&a[i]);
		if(a[i]>m) flag=0;
	}
	if(flag==0) {
    
    
		puts("-1");
		return 0;
	}
	int l=0,r=0,p=1;
	LL sum=0;
	dp[0]=0;
	dp[1]=a[1];
	q[r++]=0;
	for(int i=1; i<=n; i++) {
    
    
		sum+=a[i];
		while(sum>m) sum-=a[p++];
		while(l<r && q[l]<p) l++;
		while(l<r && a[q[r-1]]<=a[i]) r--;
		q[r++]=i;
		dp[i]=dp[p-1]+a[q[l]];
		for(int j=l; j<r-1; j++) 
			dp[i]=MIN(dp[i],dp[q[j]]+a[q[j+1]]);
	}
	printf("%lld\n",dp[n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Ljnoit/article/details/106219044