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. 在DHTML中把整个文档的各个元素作为对象处理的技术是:()

    在DHTML中把整个文档的各个元素作为对象处理的技术是:() A.HTML B.CSS C.DOM D.Script(脚本语言) 解答:C DOM:文档对象模型

  2. (转)S5PV210 三个Camera Interface/CAMIF/FIMC的区别

    原文出处:http://blog.csdn.net/kickxxx/article/details/7728947 S5PV210有三个CAMIF单元,分别为CAMIF0 CAMIF1和CAMIF2. ...

  3. CentOS下screen 命令详解

    一.背景 系统管理员经常需要SSH 或者telent 远程登录到Linux 服务器,经常运行一些需要很长时间才能完成的任务,比如系统备份.ftp 传输等等.通常情况下我们都是为每一个这样的任务开一个远 ...

  4. 【Java集合的详细研究2】浅谈Arrays.asList的使用

    首先,该方法是将数组转化为list.有以下几点需要注意: (1)该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean) (2)该方法将数组与列表 ...

  5. Oracle-批量修改语句及相关知识点

    问: 有两张表A和B,结构相同,数据量一致,比如都有x,y和z列且都有n行,x为主键,完全相等,如何把表B的y列的数据赋值给A的y列? 我写的是1 update A set A.y=B.y where ...

  6. c++ word类型

    word就是16位的数据 随着机器的发展,C++语言本身并没有规定short的位数,不一定是十六位的(随着计算机的发展,可能改变).但word将永远是16位的--机器发展后只需要修改,typedef ...

  7. c++ list erase()

    STL中的容器按存储方式分为两类,一类是按以数组形式存储的容器(如:vector .deque):另一类是以不连续的节点形式存储的容器(如:list.set.map).在使用erase方法来删除元素时 ...

  8. 51地图标注接口(EZMarker API)

    功能 在很多时候,您需要您的用户标出一个位置,比如:一个房地产网站,用户在登记新楼盘的时候,就需要在地图上标出这个楼盘的位置,这个时候就可以用到本接口. 地图标注接口(EZMarker API)是我要 ...

  9. POJ 1655 Balancing Act(求树的重心--树形DP)

    题意:求树的重心的编号以及重心删除后得到的最大子树的节点个数size,假设size同样就选取编号最小的. 思路:随便选一个点把无根图转化成有根图.dfs一遍就可以dp出答案 //1348K 125MS ...

  10. MySQL<数据库和表的基本操作>

    数据库和表的基本操作 数据库基础知识 创建数据库 就是在数据库系统中划分一块存储数据的空间 CREATE DATABASE itcast; 查看数据库 SHOW CREATE DATABASE 数据库 ...