zoukankan      html  css  js  c++  java
  • [LUOGU] P4767 [IOI2000]邮局

    https://www.luogu.org/problemnew/show/P4767

    四边形不等式好题!

    可以设f[i][j]表示前i个村庄,建了j个邮局的最小代价。

    转移:f[i][j]=min{f[k][j-1]+dis[k+1][i]}

    也就是枚举断点,断点后整个区间建造一个邮局并强制整个区间都选择它。

    这个邮局在哪里最优呢?由人类智慧知,在中位数处最优。

    注意到这样的转移下,时间复杂度是O(m*n^2)的,不行

    这是一个前缀问题,但是同时它也是一个区间问题,回忆四边形不等式的形式,尝试套上去

    至此,我们就有了O(nm)的优秀做法。

    (证明暂时不会,有会证明的欢迎留言..)

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    inline int rd(){
      int ret=0,f=1;char c;
      while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
      while(isdigit(c))ret=ret*10+c-'0',c=getchar();
      return ret*f;
    }
    
    const int MAXN=3005;
    
    int n,m;
    int val[MAXN],sum[MAXN],dis[MAXN][MAXN];
    int f[MAXN][305],tran[MAXN][305];
    
    int main(){
      memset(f,0x3f,sizeof(f));
      n=rd();m=rd();
      for(int i=1;i<=n;i++) val[i]=rd();
      sort(val+1,val+1+n);
      for(int i=1;i<=n;i++) sum[i]=sum[i-1]+val[i];
      for(int i=1;i<=n;i++)
        for(int j=i+1;j<=n;j++)
          dis[i][j]=dis[i][j-1]+val[j]-val[i+j>>1];
      for(int i=1;i<=n;i++) f[i][1]=dis[1][i];
      int mn=1<<30,mnid;
      for(int j=2;j<=m;j++){
        tran[n+1][j]=n-1;
        for(int i=n;i>=j;i--){
          for(int k=tran[i][j-1];k<=tran[i+1][j];k++){
            if(f[k][j-1]+dis[k+1][i]<f[i][j]){
              f[i][j]=f[k][j-1]+dis[k+1][i];
              tran[i][j]=k;
            }
          }
        }
      }
      cout<<f[n][m];
      return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9347976.html

  • 相关阅读:
    harbor私有仓库搭建
    为普通用户添加sudo权限
    进程节点占用磁盘空间
    influxdb做prometheus永久存储
    prometheus监控linux进程
    Redis一主两从搭建
    ELK搭建
    redis geo操作
    k8s 1.16.3 yaml声明变化
    k8s启动Pod遇到CrashLoopBackOff的解决方法
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9347976.html
Copyright © 2011-2022 走看看