Acwing P298 围栏
Analysis
①首先将所有粉刷匠,按照必须刷的小木块Si从小到大排序.
上面这个操作为了保证我们可以顺序处理.
②我们可以设f[i][j]表示为,前i个粉刷匠,刷了前i个木块.可以有些木块选择不刷
状态确定好了后,我们分两种情况讨论.
第i个粉刷匠不工作,那么
f[i][j]=f[i−1][j]
第j个木板不刷,那么
f[i][j]=f[i][j−1]
.
结合上面的讨论,我们不难发现,
f[i][j]=max(f[i−1][j],f[i][j−1])
接下来的问题就是,如果说粉刷匠工作,而且也还刷第j个木块,那么我们不得不仔细思考.
对于一个粉刷匠而言,如果说聘请他工作,那么显然我们有几个条件.
他粉刷的区间长度,至少为1,最多为Li.
他粉刷的区间内必须包括Si这个小木块.
粉刷区间左端点,必须小于等于Si
综上所述我们不妨设置一个粉刷匠粉刷的区域为[k+1,j]
那么根据上面所说的条件,我们将它转换为数学计算机语言,如下面这个式子所示.
k+1≤si≤j 1≤j−(k+1)≤Li K≤Si−1
综上所述,我们可以将状态转移方程一步步出来.
f[i][j]=maxf[i−1][j],f[i][j−1],f[i][j] f[i][j]=maxj−Li≤k≤Si−1(f[i][j],f[i−1][k]+Pi∗(j−(k+1)+1))
得出了一个朴素的状态转移方程,我们不得不进行转换一下.
f[i][j]=maxj−Li≤k≤Si−1(f[i][j],f[i−1][k]+Pi∗(j−(k+1)+1))
我们不妨去掉一个括号.
f[i][j]=maxj−Li≤k≤Si−1(f[i][j],f[i−1][k]+Pi∗(j−k))
上面的一次次变换,让我们发现了,如果说我们要求的f[i][j]要选取到最大值,那么我们核心目标点就是让Max函数内部的
f[i−1][k]−Pi∗k
尽量地大.
尽然如此的话,我们发现K的取值是一个范围,但是我们并不关心这个范围内所有的数值,我们唯一的关心点就是这个范围的最大值.也就是最大的f[i−1][k]
一个区间,最大值,这些关键字眼,不得不让我们思考一下单调队列这种优秀的数据结构.因此我们把中心放到单调队列上面.
单调队列的核心要点,就是生存能力的判断.
我们逐步入手,下面给出几个判断依据.
我们设当前有两个点,一个是k1,另外一个是k2.
我们发现当前点,如果说k1<k2,也就是k2后出现.
我们将k1,k2代入到我们的状态转移方程中的决定部分.
那么将k1代入
f[i−1][k1]−Pi∗k1
再将k2代入其中
f[i−1][k2]−Pi∗k2
我们发现如果说我们再满足下面这个条件的话,那么k2一定优于k1
于是可以用单调队列维护了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define int long long
#define maxn 16000+10
#define maxm 1000+10
using namespace std;
inline int read()
{
int x=;
bool f=;
char c=getchar();
for(; !isdigit(c); c=getchar()) if(c=='-') f=;
for(; isdigit(c); c=getchar()) x=(x<<)+(x<<)+c-'';
if(f) return x;
return -x;
}
inline void write(int x)
{
if(x<){putchar('-');x=-x;}
if(x>)write(x/);
putchar(x%+'');
}
int n,m;
int deque[maxn];
int dp[maxm][maxn];
struct node
{
int l,p,s;
}x[maxm];
inline bool cmp(node x,node y)
{
return x.s<y.s;
}
inline int calc(int i,int k)
{
return dp[i-][k]-x[i].p*k;
}
signed main()
{
n=read();m=read();
for(int i=;i<=m;i++)
{
x[i].l=read();x[i].p=read();x[i].s=read();
}
sort(x+,x+m+,cmp);
for(int i=;i<=m;i++)
{
int head=,tail=;
for(int k=max(0ll,x[i].s-x[i].l);k<=x[i].s-;k++)
{
while(head<=tail&&calc(i,deque[tail])<=calc(i,k)) tail--;
deque[++tail]=k;
}
for(int j=;j<=n;j++)
{
dp[i][j]=max(dp[i-][j],dp[i][j-]);
if(j>=x[i].s)
{
while(head<=tail&&deque[head]<j-x[i].l) head++;
if(head<=tail)
dp[i][j]=max(dp[i][j],calc(i,deque[head])+x[i].p*j);
}
}
}
write(dp[m][n]);
return ;
}
请各位大佬斧正(反正我不认识斧正是什么意思)
Acwing P298 围栏的更多相关文章
- AcWing 329. 围栏障碍训练场
大型补档计划 题目链接 考虑模拟这个过程. \(f[i][0 / 1]\) 表示从第 \(i\) 个围栏的 左/右端点开始往下走,走到原点的最小花费. 转移很容易想到,就是考虑找到一个往下走第一个碰到 ...
- AcWing 298. 围栏 (POJ1821)
标签(空格分隔): dp 单调队列优化 题目描述 有N块木板从左到右排成一行,有M个工匠对这些木板进行粉刷,每块木板至多被粉刷一次. 第 i 个木匠要么不粉刷,要么粉刷包含木板 \(S_i\) 的,长 ...
- csp-s 考前刷题记录
洛谷 P2615 神奇的幻方 洛谷 P2678 跳石头 洛谷 P1226 [模板]快速幂||取余运算 洛谷 P2661 信息传递 LOJ P10147 石子合并 LOJ P10148 能量项链 LOJ ...
- Acwing:102. 最佳牛围栏(前缀和 + 二分)
农夫约翰的农场由 NN 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头. 约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最 ...
- AcWing 102. 最佳牛围栏
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头. 约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大 ...
- AcWing 309. 装饰围栏
题目链接 这道题与下一章的数位\(dp\)解题思路十分一致. 把寻找答案变成按位(并且是字典序从小到大)枚举当前这一位可以填的情况. 通过\(dp\)预处理的信息告诉我们可行性,就可以把答案紧逼到一个 ...
- Acwing-102-最佳牛围栏(二分,实数)
链接: https://www.acwing.com/problem/content/104/ 题意: 农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过200 ...
- 地理围栏算法解析(Geo-fencing)
地理围栏算法解析 http://www.cnblogs.com/LBSer/p/4471742.html 地理围栏(Geo-fencing)是LBS的一种应用,就是用一个虚拟的栅栏围出一个虚拟地理边界 ...
- 【GPS】 数据围栏
1.记录gps信息,定位类型 gps agps ,偏移量 2.根据id检索用户 gps 历史记录 3.创建围栏 4.围栏内用户检索(先实现 圆形和矩形) 5.判断一个点是否进出围栏 应用场景: o ...
随机推荐
- Fedora30 install VS Code
We currently ship the stable 64-bit VS Code in a yum repository, the following script will install t ...
- Python-14-常用模块
一.time&datatime 在Python中,通常有这几种方式来表示时间: 时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量 ...
- docker容器与主机之间的文件复制
Easy—— 注意:“容器名与文件路径中间的冒号后不能有空格!” 1.从容器复制到主机: sudo docker cp 容器名:文件路径 主机文件/夹路径 2.从主机复制复制到容器: sudo doc ...
- vue3生命周期
介绍 vue3的生命周期函数,可以按需导入到组件中,且只能在 setup() 函数中使用 示例 import { onMounted, onUpdated } from '@vue/compositi ...
- go语言学习 ---struct 对象的序列化和反序列化(xml)
实例1: //main package main import ( "encoding/xml" "fmt" ) type person struct { Na ...
- 【CF1095F】 Make It Connected(最小生成树)
题目链接 如果没有特殊边的话显然答案就是权值最小的点向其他所有点连边. 所以把特殊边和权值最小的点向其他点连的边丢一起跑最小生成树就行了. #include <cstdio> #inclu ...
- python day 11: 类的补充,元类,魔法方法,异常处理
目录 python day 11 1. 类的补充 1.1 通过反射来查找类,创建对象,设置对象的属性与方法 1.2 类的魔法方法:getitem,setitem 1.3 元类__metaclass__ ...
- MySQL Case--应用服务器性能瓶颈导致慢SQL
在分析优化慢SQL时,除考虑慢SQL对应执行计划外,还需要考虑 1. 慢SQL发生时间点的数据库服务器性能 2.慢SQL发生时间点的应用程序服务器性能 3. 慢SQL发生时间点数据库服务器和应用服务器 ...
- Python——迭代器&可迭代对象
可迭代对象 什么是对象: Python中,一切皆对象.一个变量,一个列表,一个字符串,文件句柄,函数等等都可称为一个对象.一个对象就是一个实例,就是实实在在的东西. 什么是迭代 迭代就是一个重复的过程 ...
- @JsonIgnore注解
注解名称:@JsonIgnore 作用:在实体类向前台返回数据时用来忽略不想传递给前台的属性或接口. Eg:User实体中会有字段password字段,当返回用户信息给前台的时候,当然是不希望将pas ...