ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[洛谷P3620] APIO/CTSC 2007 数据备份

2019-11-03 23:56:07  阅读:228  来源: 互联网

标签:洛谷 int 备份 CTSC 网络 数据备份 电缆 配对 办公楼


问题描述

你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份。然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣。

已知办公楼都位于同一条街上。你决定给这些办公楼配对(两个一组)。每一对办公楼可以通过在这两个建筑物之间铺设网络电缆使得它们可以互相备份。

然而,网络电缆的费用很高。当地电信公司仅能为你提供 K 条网络电缆,这意味着你仅能为 K 对办公楼(或总计 2K 个办公楼)安排备份。任一个办公楼都属于唯一的配对组(换句话说,这 2K 个办公楼一定是相异的)。

此外,电信公司需按网络电缆的长度(公里数)收费。因而,你需要选择这 K对办公楼使得电缆的总长度尽可能短。换句话说,你需要选择这 K 对办公楼,使得每一对办公楼之间的距离之和(总距离)尽可能小。

下面给出一个示例,假定你有 5 个客户,其办公楼都在一条街上,如下图所示。这 5 个办公楼分别位于距离大街起点 1km, 3km, 4km, 6km 和 12km 处。电信公司仅为你提供 K=2 条电缆。

img

上例中最好的配对方案是将第 1 个和第 2 个办公楼相连,第 3 个和第 4 个办公楼相连。这样可按要求使用 K=2 条电缆。第 1 条电缆的长度是 3km―1km = 2km,第 2 条电缆的长度是 6km―4km = 2 km。这种配对方案需要总长 4km 的网络电缆,满足距离之和最小的要求。

输入格式

输入文件的第一行包含整数 n 和 k,其中 n(1≤n≤100 000)表示办公楼的数目,k(1≤k≤n/2)表示可利用的网络电缆的数目。

接下来的 n 行每行仅包含一个整数(0≤s≤1000 000 000), 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。

输出格式

输出文件应当由一个正整数组成,给出将 2K 个相异的办公楼连成 K 对所需的网络电缆的最小总长度。

样例输入

5 2
1
3
4
6
12

样例输出

4

数据范围

30%的输入数据满足 n≤20。

60%的输入数据满足 n≤10000

解析

先考虑贪心。一个显然的结论是不可能跨过一些建筑物连线,这样不可能更优。那么有这么一个贪心策略:每次选择相邻点中最短的线路,然后把这条路线两边的点标记为不可选。当然这是不对的,可能不选两边带来的损失更大。有什么方法能消除后效性?

这里采用加入反悔决策的方法。设删去的边长度为\(l_i\),那么两边的长度分别为\(l_{i-1}\)、\(l_{i+1}\)。当我们选择\(l_i\)时,删去\(l_{i-1}\)、\(l_{i+1}\)的同时加入\(l_{i-1}+l_{i+1}-l_i\)的选择表示反悔。这样,就可以保证决策正确了。

由于涉及到相邻点的改变,我们可以用链表加堆来实现这个过程。

代码

#include <iostream>
#include <cstdio>
#include <queue>
#define int long long
#define N 200002
using namespace std;
priority_queue<pair<int,int> > q;
int n,k,i,pre[N],nxt[N],d[N],a[N],ans,cnt;
bool vis[N];
int read()
{
    char c=getchar();
    int w=0;
    while(c<'0'||c>'9') c=getchar();
    while(c<='9'&&c>='0'){
        w=w*10+c-'0';
        c=getchar();
    }
    return w;
}
signed main()
{
    n=read();k=read();
    for(i=0;i<n;i++){
        a[i]=read();
        if(i>=1){
            d[i]=a[i]-a[i-1];
            q.push(make_pair(-d[i],i));
            pre[i]=i-1;nxt[i]=i+1;
        }
    }
    d[0]=d[n]=1<<30;
    for(i=1;i<=k;i++){
        while(!q.empty()){
            int x=q.top().second,dis=-q.top().first;
            q.pop();
            if(vis[x]) continue;
            ans+=dis;
            vis[pre[x]]=vis[nxt[x]]=1;
            d[x]=d[pre[x]]+d[nxt[x]]-d[x];
            q.push(make_pair(-d[x],x));
            nxt[pre[pre[x]]]=x;
            pre[nxt[nxt[x]]]=x;
            pre[x]=pre[pre[x]];
            nxt[x]=nxt[nxt[x]];
            break;
        }
    }
    printf("%lld\n",ans);
    return 0;
} 

标签:洛谷,int,备份,CTSC,网络,数据备份,电缆,配对,办公楼
来源: https://www.cnblogs.com/LSlzf/p/11789936.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有