POJ 1821 Fence(单调队列优化DP)
题解
以前做过很多单调队列优化DP的题。
这个题有一点不同是对于有的状态可以转移,有的状态不能转移。
然后一堆边界和注意点。导致写起来就很难受。
然后状态也比较难定义。
dp[i][j]代表前i个人涂完前j个位置的最大收益。
然后转移考虑
第i个人可以不刷。dp[i][j]=dp[i-1][j];
第j个木板可以不刷dp[i][j]=dp[i][j-1];
然后当c[i].s<=j<=s[i]+l[i]-1时
dp[i][j]=p[i]*j+max(dp[i-1][k]-p[i]*k)其中j-l[i]<=k<=s[i]-1;
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
const int M=;
int dp[M][N],n,m,q[N],head,tail,ans;
struct people{
int l,p,s;
}c[M];
bool cmp(people a,people b){
return a.s<b.s;
}
int read(){
int sum=,f=;char ch=getchar();
while(ch<''||ch>''){
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<=''){
sum=sum*+ch-'';
ch=getchar();
}
return sum;
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
memset(dp,,sizeof(dp));
for(int i=;i<=m;i++){
c[i].l=read();c[i].p=read();c[i].s=read();
}
sort(c+,c++m,cmp);
for(int i=;i<=m;i++){
memset(q,,sizeof(q));
head=;tail=;
for(int j=;j<=n;j++){
dp[i][j]=max(dp[i-][j],dp[i][j-]);
if(j>=c[i].s&&j<=c[i].s+c[i].l-){
while(head<=tail&&q[head]<j-c[i].l)head++;
if(head>tail)continue;
dp[i][j]=max(c[i].p*j+dp[i-][q[head]]-c[i].p*q[head],dp[i][j]);
}
if(j<c[i].s){
while(head<=tail&&dp[i-][j]-c[i].p*j>=dp[i-][q[tail]]-c[i].p*q[tail])tail--;
q[++tail]=j;
}
}
}
printf("%d\n",dp[m][n]);
}
return ;
}
POJ 1821 Fence(单调队列优化DP)的更多相关文章
- poj 1821 Fence 单调队列优化dp
/* poj 1821 n*n*m 暴力*/ #include<iostream> #include<cstdio> #include<cstring> #incl ...
- $Poj1821\ Fence\ $单调队列优化$DP$
Poj Acwing Description 有N块木板等待被M个工匠粉刷,每块木板至多被刷一次.第i个工匠要么不粉刷,要么粉刷包含木块Si的,长度不超过Li的连续的一段木板,每粉刷一块可以得到P ...
- Dividing the Path POJ - 2373(单调队列优化dp)
给出一个n长度的区间,然后有一些小区间只能被喷水一次,其他区间可以喷水多次,然后问你要把这个区间覆盖起来最小需要多少喷头,喷头的半径是[a, b]. 对于每个只能覆盖一次的区间,我们可以把他中间的部分 ...
- poj1821 Fence(单调队列优化dp)
地址 一排N个木板,M个工匠站在不同位置$S_i$,每个人可以粉刷覆盖他位置的.最长长度为$L_i$木板段,每刷一个有$P_i$报酬.同一木板只刷一次.求最大报酬. 根据每个人的位置dp,设$f[i] ...
- 单调队列优化DP——习题收集
前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...
- 算法笔记--单调队列优化dp
单调队列:队列中元素单调递增或递减,可以用双端队列实现(deque),队列的前面和后面都可以入队出队. 单调队列优化dp: 问题引入: dp[i] = min( a[j] ) ,i-m < j ...
- 单调队列优化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股 且一次 ...
随机推荐
- git--客户端管理工具初步使用
说点废话哈 小白一枚, 今年3月份进入自己的第一家公司, 开始成为前端中的一份子,好在公司里有位和我一同进来的一位老哥带着我,从老哥身上学到的知识不多,(因为和老哥只相处工作了三个月,因为家里的事情, ...
- JavaScript学习笔记(第二天)
数组 为什么要学习数组 之前学习的数据类型,只能存储一个值(比如:Number/String.我们想存储班级中所有学生的姓名,此时该如何存储? 数组的概念 所谓数组,就是将多个元素(通常是同一类型)按 ...
- [读书笔记] Python 数据分析 (八)画图和数据可视化
ipython3 --pyplot pyplot: matplotlib 画图的交互使用环境
- linux中一次创建多个目录
linux中创建目录当然使用命令工具mkdir == (make directory),联想记忆法能让你记得牢固. 如果你要创建几个目录,例如:dir1目录,dir2目录,dir3目录可以这样 mkd ...
- u-boot启动代码start.S详解
(1)定义入口.由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本 ...
- Collection、List、Set、Map之间的关系
初学java,单个的接触有点迷糊,所以总结下他们的关系 一.关系 Collection --List:以特定顺序存储 --ArrayList.LinkList.Vector --Set:不能包含重复的 ...
- cogs 2170. 大整数取模
2170. 大整数取模 ★ 输入文件:bigint.in 输出文件:bigint.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] 输入正整数n和m,输出n mo ...
- 树莓派学习笔记—— 源码方式安装opencv
0.前言 本文介绍怎样在树莓派中通过编译源码的方式安装opencv,并通过一个简单的样例说明怎样使用opencv. 很多其它内容请參考--[树莓派学习笔记--索引博文] 1.下载若干依 ...
- apache rewrite 正則表達式基础
用了好几次rewrite,用的次数不是非常多,每次都忘,都得又一次上网上找一堆现看,总结一下,以免以后忘了 =====================分隔符===================== ...
- python爬虫 分页获取图片并下载
--刚接触python2天,想高速上手,就写了个爬虫,写完之后,成就感暴增,用起来顺手多了. 1.源代码 #coding=utf-8 import urllib import re class Pag ...