[POJ1821]Fence

本文详细介绍了一种基于动态规划的算法优化技巧,通过单调队列优化状态转移方程,解决了一个涉及工匠粉刷木板的问题。文章首先介绍了题目的背景,随后给出了具体的算法思路,包括如何对工匠进行排序以保证有序性,以及如何通过状态转移方程来求解最优解。特别地,文章聚焦于如何优化第三个状态转移方程,通过将部分表达式视为整体并利用单调队列进行优化,实现了高效的求解过程。最后,提供了完整的AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题面描述

传送门

思路

首先我们先按照 s i s_i si来排序,保证工匠的有序性。

F i , j F_{i,j} Fi,j为现在是第 i i i个工匠粉刷前 j j j个木板(有的木板可以不刷)

状态转移方程为:
  F i , j = max ⁡ { F i − 1 , j ( 这 个 工 匠 太 懒 了 , 不 干 活 ) F i , j − 1 ( 这 个 工 匠 不 刷 第 j 个 木 板 ) F i − 1 , k + p i ∗ ( j − k ) , j ≥ s i , j − l i ≤ k ≤ s i − 1 } \large\ F_{i,j}=\max\begin{Bmatrix}F_{i-1,j}(这个工匠太懒了,不干活)\\F_{i,j-1}(这个工匠不刷第j个木板)\\F_{i-1,k}+p_i*(j-k),j\ge s_i,j-l_i\le k\le s_i-1\end{Bmatrix}  Fi,j=maxFi1,j()Fi,j1(j)Fi1,k+pi(jk),jsi,jliksi1

主要如何优化第三个转移方程。

变式可以发现:

F i − 1 , k + p i ∗ ( j − k ) = F i − 1 , k − p i ∗ k + p i ∗ j F_{i-1,k}+p_i*(j-k)=F_{i-1,k}-p_i*k+p_i*j Fi1,k+pi(jk)=Fi1,kpik+pij

F i − 1 , k − p i ∗ k F_{i-1,k}-p_i*k Fi1,kpik看作一个整体,就可以进行单调队列优化了。

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define gc getchar()
using namespace std;
const int K=110;
const int N=1.6e4+10;
struct node{int s,l,p;}a[K];
bool cmp(node x,node y){return x.s<y.s;}
int f[K][N],q[N];
inline int calc(int i,int k){return f[i-1][k]-a[i].p*k;}
int main()
{
	int n,m;scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d%d%d",&a[i].l,&a[i].p,&a[i].s);
	sort(a+1,a+m+1,cmp);
	for(int i=1;i<=m;i++)
	{
		int head=1,tail=0;
		for(int k=max(0,a[i].s-a[i].l);k<=a[i].s-1;k++)
		{
			while(head<=tail&&calc(i,k)>calc(i,q[tail]))--tail;//维护一个下降队列
			q[++tail]=k;
		}
		for(int j=1;j<=n;j++)
		{
			f[i][j]=max(f[i-1][j],f[i][j-1]);
			if(j>=a[i].s)
			{
				while(head<=tail&&q[head]<j-a[i].l)++head;//踢掉不合法的
				if(head<=tail)f[i][j]=max(f[i][j],calc(i,q[head])+a[i].p*j);
			}
		}
	}
	printf("%d\n",f[m][n]);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值