标签:
http://poj.org/problem?id=3017
Description
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.
Input
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
Output one integer which is the minimum sum of the maximum integer of each part. If no such cuttings exist, output ?1.
Sample Input
8 17 2 2 2 8 1 8 2 1
Sample Output
12
/** poj3017 dp+单调队列优化 题目大意:给定一个数列,把这个数列进行分割,每个小段的和不能超过m,求如何分配能使得每段的最大值的总和最小 解题思路:这道题猛地一看好像一个最大值最小化,其实并不是,这道题是求所有段最大值的和最小。我们用dp来写 dp[i]=dp[j]+max(x[j+1],x[j+2],x[j+3]...x[i]).其中(x[j+1],x[j+2],x[j+3]...x[i])<=m.复杂度是O(n^2) 我们采取单调队列的思想优化一下,O(n)的复杂度 */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; const int maxn=100005; LL a[maxn],q[maxn],m,dp[maxn]; int n; int main() { while(~scanf("%d%lld",&n,&m)) { LL pos=0,last=0,cnt=0; int front=1,rear=0,flag=0; dp[0]=0; for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); if(a[i]>m)flag=1; cnt+=a[i]; while(cnt>m)cnt-=a[++pos]; while(front<=rear&&a[q[rear]]<=a[i]) rear--; q[++rear]=i; while(front<=rear&&q[front]<=pos) front++; last=pos; /// printf("(%d ",last+1); dp[i]=0x3f3f3f3f3f3f3f3f; for(int j=front;j<=rear;j++) { dp[i]=min(dp[i],dp[last]+a[q[j]]); last=q[j]; } /// printf("%d %d)\n",i,dp[i]); } if(flag) printf("-1\n"); else printf("%lld\n",dp[n]); } return 0; }
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/45822449