[POJ1821]Fence(单调队列优化dp)
[poj1821]Fence
有 N 块木板从左至右排成一行,有 M 个工匠对这些木板进行粉刷,每块木板至多被粉刷一次。第 i 个工匠要么不粉刷,要么粉刷包含木板 Si 的,长度不超过Li 的连续一段木板,每粉刷一块木板可以得到 Pi 的报酬。求如何安排能使工匠们获得的总报酬最多。
1<=N<=16000,1<=M<=100
输入
NK
L1 P1 S1
L2 P2 S2
...
LK PK SK
输出
输出包含一个整数,即最大总收入。
样例输入:
8 4
3 2 2
3 2 3
3 3 5
1 1 7
样例输出:
17
先把所有工匠按照\(Si\)排序,这样一来,每个工匠粉刷的木板一定在上一个工匠之后,使我们能够按顺序进行线性 DP。
设\(F[i,j]\)表示安排前\(i\)个工匠粉刷前\(j\)块木板(可以有空着不刷的木板),工匠能获得的最多报酬。
1.第\(i\)个工匠可以什么也不刷,此时\(F[i,j]=F[i-1,j]\)。
2.第\(j\)块木板可以空着不刷,此时\(F[i,j]=F[i,j-1]\)。
3.第\(i\)个工匠粉刷第\(k+1\)块到第\(j\)块木板。根据题意,该工匠粉刷总数不能超过\(Si\),所以需要满足: \(k+1<=Si<=j\)并且\(j-k<=Li\)。于是,有状态转移方程:
\]
我们重点来看这个方程怎么优化。首先,在考虑内层循环\(j\)以及决策\(k\)时,可把外层循环变量\(i\)看作定值。这样一来,状态转移方程中的各项可分为两部分:
1.\(Pi*j\),除定值\(i\)外,只有状态变量\(j\)。
2.\(F[i-1,k]-Pi*k\),除定值\(i\)外,只有决策变量\(k\)。状态转移方程可写为:
\]
当 \(j\) 增大时,\(k\) 的取值范围上界 \(Si-1\) 不变,下界 \(j-Li\) 变大。这时
我们来比较任意两个决策 \(k1\) 和 \(k2\)。不妨设 \(k1<k2<=Si-1\)。因为 \(k2\) 比 \(k1\) 更靠后,所以随着 \(j\) 的增加,\(k1\) 会比 \(k2\) 更早从范围\([j-Li,Si-1]\)中排除。如果还满足\(F[i-1,k1]-Pi*k1<=F[i-1,k2]-Pi*k2\)那么就意味着 k2 不但比 k1 优,还比 k1 的存活时间更长。在这种情况下,k1 就是一个无用的决策,应该被排除出候选集合。综上所述,我们可以维护一个决策点 k 的单调递增。数值\(F[i-1,k]-Pi*k\) 单调递减的队列。只有这个队列中的决策才有可能在某一时刻成为最优决策。这个单调队列支持如下操作:
1.当 j 变大时,检查队头元素,把小于 j-Li 的决策出队。
2.需要查询最优决策时,队头即为所求。
3.有一个新的决策需要加入队列时,在队尾检查 F[i-1,k]-Pi*k 的单调性,把无用决策从队尾直接出队,最后把新决策加入队列。
在本题具体来说,当内循环开始时(j==Si),建立一个空的单调队列,把\(max(Si-Li,0),Si-1\)中的决策依次加入候选集合(执行操作 3)。对于每个 \(j=Si~k\),先在队头检查决策合法性(操作 1),然后取队头为最优决策(操作 2)进行状态转移。因为每个决策至多入队,出队一次,故转移的时间复杂队均弹 \(O(1)\)。整个算法的时间复杂度为 \(O(NM)\)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int read()
{
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*w;
}
int dp[110][16010];
int team[16010];
struct node{
int l,p,s;
}f[110];
int cmp(node p,node q)
{
return p.s<q.s;
}
int main()
{
int n=read(),k=read();
for(int i=1;i<=k;i++)
{
f[i].l=read();f[i].p=read();f[i].s=read();
}
sort(f+1,f+1+k,cmp);
for(int i=1;i<=k;i++)
{
int l=1,r=0;
for(int p=max(0,f[i].s-f[i].l);p<f[i].s;p++)
{
while(l<=r&&dp[i-1][team[r]]-f[i].p*team[r]<=dp[i-1][p]-f[i].p*p)
r--;
team[++r]=p;
}
for(int j=1;j<=n;j++)
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if(j>=f[i].s)
{
while(l<=r&&team[l]<j-f[i].l) l++;
if(l<=r)
dp[i][j]=max(dp[i][j],dp[i-1][team[l]]+f[i].p*(j-team[l]));
}
}
}
cout<<dp[k][n];
}
[POJ1821]Fence(单调队列优化dp)的更多相关文章
- $Poj1821\ Fence\ $单调队列优化$DP$
Poj Acwing Description 有N块木板等待被M个工匠粉刷,每块木板至多被刷一次.第i个工匠要么不粉刷,要么粉刷包含木块Si的,长度不超过Li的连续的一段木板,每粉刷一块可以得到P ...
- poj1821 Fence(单调队列优化dp)
地址 一排N个木板,M个工匠站在不同位置$S_i$,每个人可以粉刷覆盖他位置的.最长长度为$L_i$木板段,每刷一个有$P_i$报酬.同一木板只刷一次.求最大报酬. 根据每个人的位置dp,设$f[i] ...
- POJ 1821 Fence(单调队列优化DP)
题解 以前做过很多单调队列优化DP的题. 这个题有一点不同是对于有的状态可以转移,有的状态不能转移. 然后一堆边界和注意点.导致写起来就很难受. 然后状态也比较难定义. dp[i][j]代表前i个人涂 ...
- poj 1821 Fence 单调队列优化dp
/* poj 1821 n*n*m 暴力*/ #include<iostream> #include<cstdio> #include<cstring> #incl ...
- 单调队列优化DP——习题收集
前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- bzoj1855: [Scoi2010]股票交易--单调队列优化DP
单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
随机推荐
- Centos7硬盘空间扩容(vmware虚拟机)
1. 查看系统挂载点 df -h 2. 系统关机 init 0 硬盘1空间修改为100G,保存并启动 3.查看磁盘 fdisk -l /dev/sda空间加上去了 3. 硬盘分区 fdisk /dev ...
- python学习笔记(十九)面向对象编程,类
一.面向对象编程 面向对象,是一种程序设计思想. 编程范式:编程范式就是你按照什么方式去编程,去实现一个功能.不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,两种最重要的编程范式分 ...
- 04 全局配置,java 编意默认版本,1.6.修改配置
https://www.cnblogs.com/liu-s/p/5371289.html <!-- 修改Intellij Idea 创建maven项目默认Java编译版本 --> < ...
- 如何从Word带图粘贴到编辑器中
这种方法是servlet,编写好在web.xml里配置servlet-class和servlet-mapping即可使用 后台(服务端)java服务代码:(上传至ROOT/lqxcPics文件夹下) ...
- B/S大文件断点续传
一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输. ...
- [NOIP2014]飞扬的小鸟[DP]
[NOIP2014]飞扬的小鸟 ——!x^n+y^n=z^n 题目描述: Flappy Bird 是一款风靡一时的休闲手机游戏.玩家需要不断控制点击手机屏幕的频率来调节小鸟的飞行高度,让小鸟顺利通过画 ...
- js点击获取—通过JS获取图片的相对坐标位置
一.通过JS获取鼠标点击时图片的相对坐标位置 源代码如下所示: <!DOCTYPE html> <html lang="en"> <head> ...
- localhost和127.0.0.0
,网络通信知识. 127.0.0.1是环回地址,只有本机可以访问 0.0.0.0是本机地址,内网外网均可以访问 localhost是本机域名,只有本机可以访问 ip是分五类
- flask-script实现自动刷新页面调试
本文flask==1.0.2 1.导入extension包 from flask_script import Manager 2.使用manager管理工具 app = Flask(__name__) ...
- IDEA 服务启动报:No buffer space available (maximum connections reached): connect的解决方案。
错误提示:严重: Error starting endpointjava.io.IOException: Unable to establish loopback connectionat sun.n ...