当前位置: 首页 > news >正文

信息学奥赛一本通 1611:仓库建设 | 洛谷 P2120 [ZJOI2007] 仓库建设

【题目链接】

ybt 1611:仓库建设
洛谷 P2120 [ZJOI2007] 仓库建设

【题目考点】

1. 动态规划:斜率优化动规

【解题思路】

状态定义

  • 阶段:将前i个工厂的产品都运进仓库
    由于只能往编号更大的工厂运货,为了保证前i个工厂的货都进仓库,那么第i工厂必须建立仓库。
  • 决策:在哪个工厂建立仓库
  • 策略:选择工厂建立仓库的方案
  • 策略集合:要想将前i个工厂的产品都运进仓库,建立仓库的方案
  • 条件:费用最小
  • 统计量:费用

状态定义 d p i dp_i dpi:考虑将前 i i i个工厂的产品都运进仓库,且一定在第 i i i工厂建立仓库的所有方案中,费用最小的方案的费用。
初始状态 d p 0 = 0 dp_0=0 dp0=0

状态转移方程

  • 策略集合:要想将前i个工厂的产品都运进仓库,建立仓库的方案
  • 分割策略集合:由于最后一个仓库已经必须建在第 i i i工厂,那么根据倒数第二个仓库建立的位置分割策略集合。

设倒数第二个仓库建立在工厂 j j j j j j最小可以为0,也就是不建立倒数第二个仓库,一共只在第 i i i工厂建一个仓库。 j j j最大可以为 i − 1 i-1 i1,因此 0 ≤ j ≤ i − 1 0\le j \le i-1 0ji1

  • 在第 j j j工厂建立仓库后,将前 j j j个工厂的产品都运进仓库,且在第 j j j工厂建立仓库的最小费用为 d p j dp_j dpj
  • j + 1 j+1 j+1工厂的产品需要运到第 i i i工厂的仓库,有 p j + 1 p_{j+1} pj+1个产品,运送距离为 x i − x j + 1 x_i-x_{j+1} xixj+1,费用为 p j + 1 ( x i − x j + 1 ) p_{j+1}(x_i-x_{j+1}) pj+1(xixj+1)
    j + 2 j+2 j+2工厂的产品需要运到第 i i i工厂的仓库,有 p j + 2 p_{j+2} pj+2个产品,运送距离为 x i − x j + 2 x_i-x_{j+2} xixj+2,费用为 p j + 2 ( x i − x j + 2 ) p_{j+2}(x_i-x_{j+2}) pj+2(xixj+2)
    。。。
    i − 1 i-1 i1工厂的产品需要运到第 i i i工厂的仓库,有 p i − 1 p_{i-1} pi1个产品,运送距离为 x i − x i − 1 x_i-x_{i-1} xixi1,费用为 p i − 1 ( x i − x i − 1 ) p_{i-1}(x_i-x_{i-1}) pi1(xixi1)
    i i i工厂的产品需要运到第 i i i工厂的仓库,有 p i p_{i} pi个产品,运送距离为 x i − x i x_i-x_{i} xixi,费用为 p i ( x i − x i ) p_{i}(x_i-x_{i}) pi(xixi)
    将第 j + 1 j+1 j+1工厂到第 i i i工厂的产品运送到第 i i i工厂的仓库的总费用为 ∑ k = j + 1 i p k ( x i − x k ) = ∑ k = j + 1 i x i p k − ∑ k = j + 1 i x k p k \sum_{k=j+1}^{i}p_k(x_i-x_k)=\sum_{k=j+1}^{i}x_ip_k-\sum_{k=j+1}^{i}x_kp_k k=j+1ipk(xixk)=k=j+1ixipkk=j+1ixkpk
    = x i ∑ k = j + 1 i p k − ∑ k = j + 1 i x k p k =x_i\sum_{k=j+1}^ip_k-\sum_{k=j+1}^{i}x_kp_k =xik=j+1ipkk=j+1ixkpk
    x k p k x_kp_k xkpk序列的前缀和为 s x p sxp sxp p p p序列的前缀和为 s p sp sp,因此:
    ∑ k = j + 1 i p k ( x i − x k ) = x i ( s p i − s p j ) − ( s x p i − s x p j ) \sum_{k=j+1}^{i}p_k(x_i-x_k)=x_i(sp_i-sp_j)-(sxp_{i}-sxp_{j}) k=j+1ipk(xixk)=xi(spispj)(sxpisxpj)
  • 在第 i i i工厂建仓库需要费用 c i c_i ci
  • 对于 j j j的所有取整情况取最小值

综上,考虑将前 i i i个工厂的产品都运进仓库,且一定在第 i i i工厂建立仓库的最小的方案的费用
d p i = m i n { d p j + x i ( s p i − s p j ) − ( s x p i − s x p j ) + c i } , 0 ≤ j ≤ i − 1 dp_i=min\{dp_j+x_i(sp_i-sp_j)-(sxp_{i}-sxp_{j})+c_i\},0\le j \le i-1 dpi=min{dpj+xi(spispj)(sxpisxpj)+ci}0ji1

接下来进行斜率优化动规,去掉min,将与 j j j相关的量视作遍历,与 i i i相关的量视作常量,整理方程
− d p j − s x p j = − x i s p j + x i s p i − d p i − s x p i + c i -dp_j-sxp_j=-x_isp_j+x_isp_i-dp_i-sxp_i+c_i dpjsxpj=xispj+xispidpisxpi+ci
d p j + s x p j = x i s p j + d p i + s x p i − x i s p i − c i dp_j+sxp_j=x_isp_j+dp_i+sxp_i-x_isp_i-c_i dpj+sxpj=xispj+dpi+sxpixispici
x = s p j x=sp_j x=spj y = d p j + s x p j y=dp_j+sxp_j y=dpj+sxpj k = x i k=x_i k=xi b = d p i + s x p i − x i s p i − c i b=dp_i+sxp_i-x_isp_i-c_i b=dpi+sxpixispici
则以上方程就是直线方程 y = k x + b y=kx+b y=kx+b,对于每个 j j j的取值, ( s p j , d p j + s x p j ) (sp_j, dp_j+sxp_j) (spj,dpj+sxpj)是一个决策点,直线的斜率是固定的,看该直线经过哪条决策点时直线的截距 b b b最小,此时 d p i dp_i dpi的值就是所求的值。
该题中直线斜率 x i x_i xi随着 i i i的增大而增大,可以使用队头出队操作,取队头就是最优决策点。
斜率优化的具体原理和代码细节不再赘述,参考模板题:
信息学奥赛一本通 1607:【 例 2】任务安排 2 | 洛谷 P10979 任务安排 2

最后一个 p i > 0 p_i>0 pi>0的工厂为第 m m m工厂,所有编号大于 m m m的工厂都没有货物。因而最后一个仓库可以建在第 m m m到第 n n n工厂中的任意一个工厂,看在哪建仓库费用最小。
因此最终结果为 m i n { d p i } , m ≤ i ≤ n min\{dp_i\},m\le i \le n min{dpi}min

【题解代码】

解法1:斜率优化动规

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define N 1000005
LL n, m, x[N], p[N], sp[N], sxp[N], c[N], dp[N], ans = 1e18;//dp[i]:考虑将前i个工厂的产品都运进仓库,且一定在第i工厂建立仓库的所有方案中,费用最小的方案的费用。 
int q[N], l = 1, r = 0;//单调队列
LL X(int j)
{
	return sp[j];
} 
LL Y(int j)
{
	return dp[j]+sxp[j];
}
LL K(int i)
{
	return x[i];
}
bool cmp(LL a1, LL b1, LL a2, LL b2)//a1/b1 <= a2/b2
{
	return a1*b2 <= a2*b1; 
} 
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
 	cin >> n;
 	for(int i = 1; i <= n; ++i)
 	{
		cin >> x[i] >> p[i] >> c[i];
		sp[i] = sp[i-1]+p[i];
		sxp[i] = sxp[i-1]+x[i]*p[i];
		if(p[i] > 0)
			m = i;//m:记录最后一个有产品的工厂 
	}
 	for(int i = 1; i <= n; ++i)
 	{
 		while(l < r && cmp(Y(i-1)-Y(q[r]), X(i-1)-X(q[r]), Y(q[r])-Y(q[r-1]), X(q[r])-X(q[r-1])))
 			r--;
 		q[++r] = i-1;
 		while(l < r && cmp(Y(q[l+1])-Y(q[l]), X(q[l+1])-X(q[l]), K(i), 1))
 			l++;
 		dp[i] = dp[q[l]]+x[i]*(sp[i]-sp[q[l]])-(sxp[i]-sxp[q[l]])+c[i];
 		if(i >= m)//求dp[m]~dp[n]中的最小值 
 			ans = min(ans, dp[i]);
	}
	cout << ans;
    return 0;
} 
http://www.dtcms.com/a/106856.html

相关文章:

  • Cribl 创建路线Route
  • dubbo RPC协议
  • Unity Standard Shader 解析(二)之ForwardAdd(标准版)
  • <贪心算法>
  • 第四章、Isaacsim在GUI中构建机器人(3):添加摄像头和传感器
  • Java语言如何用AI实现文件报告的自动质检?
  • Vue3编译器深度解析:从模板编译到极致性能优化
  • 【NLP 面经 5】
  • 通过ansible+docker-compose快速安装一主两从redis+三sentinel
  • 获取最新浏览器驱动,并自动安装适配浏览器
  • 使用 Amazon Lightsail 启动并配置 WordPress 实例教程
  • LRU缓存是什么
  • DataFrame基础(不包含列删除及行相关操作)
  • error LNK2019: 无法解析的外部符号 __imp__XXXX,该符号在函数xxxxx中被引用
  • 45、Vue 中的动态组件
  • 深入理解多线程编程:从基础概念到实战应用
  • 【C++】类和对象(二)
  • 第三章 知识图谱赋能 RAG:构建结构化知识引擎
  • CoT-VLA:视觉-语言-动作模型的视觉思维链推理
  • 软件工程面试题(二十三)
  • Web服务器主动推送技术(SSE)
  • MongoDB 复制集实战
  • 笔记:docker安装(ubuntu 20.04)
  • C# 中充血模型和‌贫血模型
  • 从查重报告入手的精准论文降重秘籍
  • 基于 Spring Cloud 与 Spring Boot 的工程项目管理系统源码:重塑工程管理新范式​
  • 文件实时备份软件PanguFlow
  • zabbix监控网站(nginx、redis、mysql)
  • 在openharmony中编译部署早期vi工具(附带vi工具源码)
  • 生产管理系统如何破解汽车零部件行业追溯难痛点