Luogu2365&5785 任务安排

Luogu2365&5785 任务安排

斜率优化模板题, 是 算法竞赛进阶指南-李煜东 的斜率优化例题, 关于斜率优化的内容, 可以在这里找到

斜率优化

题目直通车

加强版

概括

n 个任务, 任务 i 有两个属性时间 Ti, 费用系数 Ci, 分批加工, 每批任务是连续的一段区间

每批任务需要经过 iiTi 时间后, 本批任务同时完成. 两批任务之间有 S 时间空闲, 每个任务花费和完成的时刻 Clocki 有关, 为 CiClock

试求完成所有任务的最小花费

1n50000s501ti,fi100

推导

设计状态, fi 表示完成前 i 个任务的花费和这 i 个任务的完成对后面任务花费的贡献.

SumCiSumTi 表示 Ci, Ti, 的前缀和

写出方程, 前 j 个的花费 + 第 j+1 到第 i 个的花费 + S 对第 i+1 个及之后的贡献.

fi=min(fj+(SumCiSumCj)SumTi+(SumCnSumCi)S)

整理得

fj=SumCjSumTi+fiSumCi(SumTiS)SumCnS

得到以 SumCj 为自变量, fj 为因变量, SumTi 为斜率, fiSumCi(SumTiS)SumCnS 为截距的函数

虽然本题不用斜优, O(n2) 能过, 但是既然能优化, 为什么不做到最快呢?为什么不复制加强版的代码呢

代码实现

struct Ms {
  long long C, T, SumC, SumT, f;
}M[5005]; // 任务属性 
struct Hull {
  long long x, y;
  unsigned Ad;
}H[5005], *Now, Then; // 下凸壳 
unsigned n, l(1), r(1);
long long S, Cst; 
int main() {
  n = RD();
  S = RD();
  M[0].SumT = S;
  for (register unsigned i(1); i <= n; ++i) {
    M[i].T = RD();
    M[i].C = RD();
    M[i].SumT = M[i - 1].SumT + M[i].T;
    M[i].SumC = M[i - 1].SumC + M[i].C; //预处理 
  }
  Cst = S * M[n].SumC;  // 截距中的一项常数 
  for (register unsigned i(1); i <= n; ++i) {
    while (l < r && ((H[l + 1].y - H[l].y) < M[i].SumT * (H[l + 1].x - H[l].x))) {
      ++l; // 弹出过气决策点 
    }
    M[i].f = M[H[l].Ad].f + (M[i].SumC - M[H[l].Ad].SumC) * M[i].SumT + Cst - M[i].SumC * S; // 转移 
    Then.Ad = i;
    Then.x = M[i].SumC;
    Then.y = M[i].f;    // 求新点坐标 
    while (l < r && ((Then.y - H[r].y) * (H[r].x - H[r - 1].x) <= (H[r].y - H[r - 1].y) * (Then.x - H[r].x))) {
      --r; // 维护下凸 
    }
    H[++r] = Then;      // 入队 
  }
  printf("%lld\n", M[n].f);
  return Wild_Donkey;
}

加强版

1n3105,1S256,|Ti|256,0Ci256

因为 Ci0, 所以 SumCi 单调, 但是 SumTi 不单调, 但是影响不大, 只影响决策时切线的斜率. 为了应对随机变化的切线斜率, 只要保存整个下凸壳, 在决策的时候二分查找即可, O(nlogn), 其余部分完全一致 (注意有负数出现).

二分查找

Hull *Binary (unsigned L, unsigned R, const long long &key) {
  if(L == R) {
    return H + L;
  }
  unsigned M((L + R) >> 1), M_ = M + 1;
  if((H[M_].y - H[M].y) < key * (H[M_].x - H[M].x)) {//Key too big 
    return Binary(M_, R, key);
  }
  return Binary(L, M, key);
}
posted @   Wild_Donkey  阅读(67)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示