Fence
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 6122   Accepted: 1972

Description

A team of k (1 <= K <= 100) workers should paint a fence which contains N (1 <= N <= 16 000) planks numbered from 1 to N from left to right. Each worker i (1 <= i <= K) should sit in front of the plank Si and he may paint only a compact interval (this means that the planks from the interval should be consecutive). This interval should contain the Si plank. Also a worker should not paint more than Li planks and for each painted plank he should receive Pi $ (1 <= Pi <= 10 000). A plank should be painted by no more than one worker. All the numbers Si should be distinct.

Being the team's leader you want to determine for each worker the interval that he should paint, knowing that the total income should be maximal. The total income represents the sum of the workers personal income.

Write a program that determines the total maximal income obtained by the K workers.

Input

The input contains: 
Input

N K 
L1 P1 S1 
L2 P2 S2 
... 
LK PK SK

Semnification

N -the number of the planks; K ? the number of the workers 
Li -the maximal number of planks that can be painted by worker i 
Pi -the sum received by worker i for a painted plank 
Si -the plank in front of which sits the worker i 

Output

The output contains a single integer, the total maximal income.

Sample Input

8 4
3 2 2
3 2 3
3 3 5
1 1 7

Sample Output

17

Hint

Explanation of the sample:

the worker 1 paints the interval [1, 2];

the worker 2 paints the interval [3, 4];

the worker 3 paints the interval [5, 7];

the worker 4 does not paint any plank

Source

 
题意:
k个工人粉刷n道墙,每个工人最多刷L[i]面,并且必须刷第S[i]面,每刷一面可以拿到P[i]的报酬。一面墙至多只能被刷一次。
思路:
首先我们按照每个工人的S进行排序,就可以保证所有工人可以做到在上一个工人之后粉刷。
用dp[i][j]来表示前i个工人粉刷前j面墙最多所得报酬。
对于一个工人i,他可以刷也可以不刷。对于一面墙j,他可以被刷也可以不被刷。
所以dp[i][j] = max(dp[i -1][j], dp[i][j -1])
dp[i][j] 的第三种情况是第i个工人从第k+1块刷到第j块。 k+1 <= Si <= j, j - k<= Li
可以得到状态转移方程:

当我们循环j,k时,可以把i看成是定值,于是对于这条方程我们可以进行一定的变形,将j和k分离。

 
当j增大时,k的取值上界不变,下界增大。
如果现在有两个决策k1,k2. 且k1 < k2 <=Si-1,如果还满足dp[i-1,k1] - Pi * k1<= dp[i -1, k2] - Pi * k2
那么k2不但比k1更优,存活时间也更长,此时k1就是一个无用决策。
所以可以维护一个决策点k单调递增,dp[i-1,k] - Pi * k单调递减的队列。
当 j 变大时,检查队头,将小于j-Li的决策出队
查询最优决策时,队头即为所求。
当有一个新的决策需要入队时,检查队尾单调性,把无用决策出队,最后新决策入队。
 
 #include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f int k, n;
struct node{
int l, s, p;
}worker[];
int que[], dp[][];
bool cmp(node a, node b)
{
return a.s < b.s;
} int cal(int i, int k)
{
return dp[i - ][k] - worker[i].p * k;
} int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
while(scanf("%d%d", &n, &k)!= EOF){
for(int i = ; i <= k; i++){
scanf("%d%d%d", &worker[i].l, &worker[i].p, &worker[i].s);
//printf("%d%d%d\n", worker[i].l, worker[i].s, worker[i].p);
}
sort(worker + , worker + + k, cmp); /*for(int i = 1; i <= k; i++){
printf("%d%d%d\n", worker[i].l, worker[i].s, worker[i].p);
}*/
for(int i = ; i <= k; i++){
int l = , r = ;
for(int x = max(, worker[i].s - worker[i].l); x <= worker[i].s - ; x++){
while(l <= r && cal(i, que[r]) <= cal(i, x)){
r--;
}
que[++r] = x;
}
for(int j = ; j <= n; j++){
dp[i][j] = max(dp[i - ][j], dp[i][j - ]);
if(j >= worker[i].s){
while(l <= r && que[l] < j - worker[i].l)l++;
if(l <= r){
dp[i][j] = max(dp[i][j], cal(i, que[l]) + worker[i].p * j);
}
//cout<<dp[i][j]<<endl;
}
}
} //int ans = 0;
//for(int i = 1; i <= n; i++){
// ans = max(ans, dp[k][i]);
//}
printf("%d\n", dp[k][n]);
}
}

poj1821 Fence【队列优化线性DP】的更多相关文章

  1. 【NOIP2017】跳房子 题解(单调队列优化线性DP)

    前言:把鸽了1个月的博客补上 ----------------- 题目链接 题目大意:机器人的灵敏性为$d$.每次可以花费$g$个金币来改造机器人,那么机器人向右跳的范围为$[min(d-g,1),m ...

  2. hdu-3401-Trade-单调队列优化的DP

    单调队列入门题... dp[i][j]:第i天.手中拥有j个股票时,获得的最大利润. 若第i天不买不卖:dp[i][j]=max(dp[i][j],dp[i-1][j]); 若第i天买         ...

  3. 一类利用队列优化的DP

    I.导入: 这是一个\(O(n^2)\)的状态和转移方程: \[f(i,j)=\left\{ \begin{aligned} f(i-1,j-1)+k \ (1\leq j)\\ \max_{k \i ...

  4. [bzoj 2726] 任务安排 (斜率优化 线性dp)

    3月14日第三题!!!(虽然是15号发的qwq) Description 机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3-N.这N个任务被分成若干批 ...

  5. HDU1024 Max Sum Plus Plus (优化线性dp)

    Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we ...

  6. Trade-----HDU3401----单调队列优化的DP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题目意思: 有T天,你每天可以以API买进,BPI卖出,最多买ASI个,最多卖BSI个 最多只能 ...

  7. 洛谷p1725 露琪诺 单调队列优化的DP

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...

  8. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  9. BestCoder Round #89 02单调队列优化dp

    1.BestCoder Round #89 2.总结:4个题,只能做A.B,全都靠hack上分.. 01  HDU 5944   水 1.题意:一个字符串,求有多少组字符y,r,x的下标能组成等比数列 ...

随机推荐

  1. Linux ad7606 驱动

    Linux中已经移植好了ad7606,位于driver/staging/iio/adc/目录中.只要在板级文件中添加device中即可. 移植参考文档: https://wiki.analog.com ...

  2. javascript -- 将数组转换为字符串:join()

    join(separator) 方法用于把数组中的所有元素放入一个字符串.元素是通过指定的分隔符进行分隔的. separator:可选,指定要使用的分隔符.如果省略该参数,则默认使用逗号作为分隔符 v ...

  3. UIView的几个枚举定义

    UIView是iOS开发最主要的视图,非常多控件都是继承它,掌握当中的几个基本枚举定义,有利益理解视图的载入和參数差别. 一.UIViewAnimationCurve UIView的基本动画变化规律 ...

  4. CentOS查看你是否有USB 3.0端口

    近来的大多数的新计算机都有了USB 3.0接口了.但是你怎么知道你的计算机有没有USB 3.0接口?这篇短文中,我们会告诉如何在Linux下知道你的系统上有USB 3还是USB3接口. 在Linux终 ...

  5. CentOS定位、查找文件的命令

    定位.查找文件的命令 命令 功能 命令 功能 which 从path中找出文件的位置 find 找出所有符合要求的文件 whereis 找出特定程序的路径 locate 从索引中找出文件位置 9.1 ...

  6. CentOS安装Emacs文本编辑器

    我这里安装的是:emacs.24.2 下载地址:http://ftp.gnu.org/pub/gnu/emacs/emacs-24.2.tar.gz 下载文件:emacs-24.2.tar.gz 步骤 ...

  7. python编码问题1

    爬虫,新手很容易遇到编码解码方面的问题.在这里总结下. 如果处理不好编码解码的问题,爬虫轻则显示乱码,重则报错UnicodeDecodeError: 'xxxxxx' codec can't deco ...

  8. [java] java 线程join方法详解

    join方法的作用是使所属线程对象正常执行run方法,而对当前线程无限期阻塞,直到所属线程销毁后再执行当前线程的逻辑. 一.先看普通的无join方法NoJoin.java public class N ...

  9. Tomcat之JSP运行原理之小试牛刀

    最近空闲看了下JSP/Servlet,以前只知道用JSP,但是对其运行原理知之甚少,今在此做些笔记,以备查阅. 首先简要描述下其运行过程,然后结合Tomcat源码作简要分析. JSP运行过程: 第一步 ...

  10. CreateEvent和SetEvent及WaitForSingleObject的使用方法

    CreateEvent: 1.函数功能: 创建一个命名或匿名的事件对象 2.函数原型: HANDLE CreateEvent(   LPSECURITY_ATTRIBUTES lpEventAttri ...