POJ 3017 單調佇列dp
Time Limit: 2000MS | Memory Limit: 131072K | |
Total Submissions: 8764 | Accepted: 2576 |
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
把序列分成若干部分,每一部分的和不超過m,求每一部分裡最大值和的最小值。
開始沒啥思路,研究了半天,感覺單調佇列dp非常的精妙,先mark一下,後面慢慢理解吧。
程式碼:
/* ***********************************************
Author :_rabbit
Created Time :2014/5/13 1:35:25
File Name :C.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
ll que[100100],a[100100],dp[100100];
int main()
{
//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
//dp 方程:f[i]=f[j]+max(x[j+1],x[j+2],...,x[i]),其中j<i,x[j+1]+x[j+2]+...+x[i]<=m;
ll n,m;
while(~scanf("%lld%lld",&n,&m)){
bool flag=1;
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
if(a[i]>m)flag=0;
}
if(!flag){
puts("-1");continue;
}
ll front=0,rear=0,p=1;
dp[1]=a[1];que[rear++]=1;
ll sum=a[1];
for(ll i=2;i<=n;i++){
sum+=a[i];
while(sum>m)sum-=a[p++];//區間和小於等於m
while(front<rear&&a[i]>=a[que[rear-1]])rear--;//單調嚴格遞減佇列
que[rear++]=i;
while(que[front]<p&&front<rear)front++;//把遠離的彈出。
dp[i]=dp[p-1]+a[que[front]];
for(ll j=front+1;j<rear;j++)
dp[i]=min(dp[i],dp[que[j-1]]+a[que[j]]);//列舉佇列中的元素,求最優解。
}
cout<<dp[n]<<endl;
}
return 0;
}
相關文章
- 單調佇列最佳化 DP佇列
- [學習筆記] 單調佇列最佳化DP - DP筆記佇列
- 單調佇列佇列
- BZOJ1044: [HAOI2008]木棍分割(dp 單調佇列)佇列
- 單調棧/單調佇列佇列
- 單調佇列雙端佇列佇列
- 單調棧 和 單調佇列佇列
- 單調棧和單調佇列佇列
- 聯賽模擬測試18 A. 施工 單調佇列(棧)優化DP佇列優化
- 簡單dp -- Common Subsequence POJ - 1458
- 單調佇列優化dp(五)——#10179. 「一本通 5.5 例 5」Banknotes佇列優化
- 佇列-單端佇列佇列
- 洛谷P4544 [USACO10NOV] Buying Feed G 題解 單調佇列最佳化DP佇列
- POJ 3071 Football(概率DP)
- POJ 3267 The Cow Lexicon(dp)
- noi.ac #289. 電梯(單調佇列)佇列
- 決策單調性DP
- 多重揹包問題的單調佇列優化佇列優化
- Sunscreen POJ - 3614(防曬油) 貪心-優先佇列佇列
- POJ1390 Blocks (區間DP)BloC
- POJ3252Round Numbers(數位dp)
- Making the Grade POJ - 3666(離散化+dp)
- RabbitMQ-簡單佇列MQ佇列
- 單向鏈式佇列佇列
- 棧,佇列,優先順序佇列簡單介面使用佇列
- 決策單調性最佳化DP
- 優先佇列的學習記錄--例題:Expedition(POJ2431)佇列
- python中佇列簡單使用Python佇列
- 佇列_單向連結串列佇列
- laravel 佇列的簡單使用Laravel佇列
- 實現簡單延遲佇列和分散式延遲佇列佇列分散式
- 佇列、阻塞佇列佇列
- kuangbin 專題二十三:二分 尺取 單調棧佇列 String佇列
- 佇列 和 迴圈佇列佇列
- 【佇列】【懶排序】佇列Q佇列排序
- 「暑期訓練」「基礎DP」 Common Subsequence (POJ-1458)
- 1284 海港 普及組 NOIP2016 佇列基礎 簡單列舉 簡單模擬 優先佇列(priority_queue)佇列
- 自定義單連結串列佇列的基本介面函式(非迴圈佇列)佇列函式
- 陣列模擬佇列 以及佇列的複用(環形佇列)陣列佇列