zoukankan      html  css  js  c++  java
  • [题解] LuoguP4767 [IOI2000]邮局

    https://www.luogu.com.cn/problem/P4767

    清一色的四边形不等式......

    其实分治优化决策单调性DP也是可以的

    (f(i,j))表示前(j)个村庄,建(i)个邮局,每个村庄和最近的邮局之间所有距离最小总和是多少。

    再设(w(i,j))表示在第(i)个到第(j)个村庄之间建一个邮局最小的距离总和。

    根据中位数定理,发现邮局一定建在([i,j])的中间。

    于是维护个前缀和啥的就可以(V^2)处理出(w)

    然后考虑DP的转移,枚举最后一个邮局建在哪个区间内,即

    [f(i,j) = maxlimits_{1 le k le j} { f(i-1,k-1)+w(k,j)} ]

    特别的,如果(j<i),那么(f(i,j) = infty)

    发现(f(i,...))只会从(f(i-1,...))转移,瞎猜一个决策点也满足单调性,于是分治优化一层的转移即可。

    虽然比四边形不等式多一个(log)...但好像跑起来也差不多)

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 3010;
    const int inf = 1e9;
    int cost[N][N], s[N][N], x[N];
    
    void solve(int *f, int *g, int l, int r, int pl, int pr) {
      if (l > r || pl > pr) {
        return;
      }   
      auto weight = [&](int i, int j) {
        return cost[i][j];
      };
      if (pl == pr) { 
        for (int i = l; i <= r; i++) {
          f[i] = g[pl - 1] + weight(pl, i);
        }
        return;
      }
      int mid = (l + r) >> 1;
      int pmid = -1;
      int mn = inf * 2;
      for (int i = pl; i <= min(mid, pr); i++) {
        if (g[i - 1] + weight(i, mid) < mn) {
          mn = g[i - 1] + weight(i, mid);
          pmid = i;
        }
      }
      f[mid] = mn;
      solve(f, g, l, mid - 1, pl, pmid);
      solve(f, g, mid + 1, r, pmid, pr);
    }
    
    int dp[N][N];
    
    int main() {
      ios::sync_with_stdio(false);
      cin.tie(0);
      int n, m;
      cin >> n >> m;
      for (int i = 1; i <= n; i++) {
        cin >> x[i];
      }   
      for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
          s[i][j] = s[i][j - 1] + x[j];
        }
      }
      for (int i = 1; i <= n; i++) {
        for (int j = i; j <= n; j++) {
          int mid = (i + j) >> 1;
          cost[i][j] = x[mid] * (mid - i + 1) - s[i][mid] + s[mid][j] - x[mid] * (j - mid + 1);
        }
      }             
      dp[1][0] = inf;
      for (int i = 1; i <= n; i++) {
        dp[1][i] = cost[1][i];
      }         
      for (int i = 2; i <= m; i++) {
        solve(dp[i], dp[i - 1], 1, n, 1, n);
        for (int j = 0; j < i; j++) {
          dp[i][j] = inf;
        } 
      }
      cout << dp[m][n] << '
    ';
      return 0;
    }
    
  • 相关阅读:
    Auto X2021 K Increasing Sequence
    拉普拉斯平滑处理 Laplace Smoothing
    博学之
    Python-生成音乐-pyshnth
    Python-Kivy ImportError: DLL load failed: 找不到指定的模块
    Python-Word模板填充-docxtpl
    Python-文字转语音-pyttsx3
    Virtual Box中Ubuntu使用"桥接网卡"不能联网而使用"网络地址转换(NAT)"却可以上网
    STM32的HAL库中的DMA_FLAG_TCIF3_7等几个宏定义的含义
    Linux下编写互相通信的驱动模块并将其加入到内核中
  • 原文地址:https://www.cnblogs.com/wxq1229/p/13357316.html
Copyright © 2011-2022 走看看