CH Round #53 -【Nescafé 32】杯NOIP模拟赛 数据备份 题解

数据备份 CH Round #53 -【Nescafé 32】杯NOIP模拟赛

描述

已知有N座办公楼位于同一条街上。你决定给这些办公楼配对(两个一组)。每一对办公楼可以通过在这两个建筑物之间铺设网络电缆使得它们可以互相备份。然而,网络电缆的费用很高。当地电信公司仅能为你提供K条网络电缆,这意味着你仅能为K对办公楼(或总计2K个办公楼)安排备份。任一个办公楼都属于唯一的配对组(换句话说,这2K个办公楼一定是相异的)。 此外,电信公司需按网络电缆的长度(公里数)收费。因而,你需要选择这K对办公楼使得电缆的总长度尽可能短。换句话说,你需要选择这K对办公楼,使得每一对办公楼之间的距离之和(总距离)尽可能小。

输入格式

输入的第一行包含整数n和k,n表示办公楼的数目,k表示可利用的网络电缆的数目。
接下来的n行每行包含一个整数s, 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。

输出格式

一个正整数,表示将2K个相异的办公楼连成k对所需的网络电缆的最小总长度。

样例输入
5 2
1
3
4
6
12
样例输出
4(即3-1+6-4)
数据范围与约定
  • 对于30%的数据,N<=20。
  • 对于60%的数据,N<=10000。
  • 对于100%的数据,N<=100000,1<=k<=n/2,0<=s<=10^9。
++++++++++++++++++++++++++++++++++++++++

哎,这道题第一感觉是dp,然后就写了一个……知道数据太大,所以也就没想得满分

可是写完后发现错误百出,先是数组的范围,然后是dp的边界……终于不懈努力,拿了55

下面我们说一下dp的做法

看到题,我们很快就能想出来一个最有结构问题,即,从0~i最优必然是要有0~i-1最优;

很明显,我们可以把状态定为f[i][j]表示0~i选j个线段的最小长度,

那么对于每一个状态必然有:

(1)i与前一个连

(2)i与后一个连

(3)i不连

我们就有了一个dp方程:

f[i][j]=min(f[i-1][j],f[i-2][j-1]+a[i]-a[i-1])

+++++++++++++代码如下++++++++++++++++++

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define INF 0x3f3f3f3f
using namespace std;
int f[20000][1000],a[50000];//鄙人不才,dp只能写到55了,哎!费了好大劲 
int n,k;
int main()
{
	scanf("%d%d",&n,&k);
	for (int i=1;i<=n;i++)cin>>a[i];
	for (int i=0;i<=n;i++)f[i][0]=0;//从这儿往下一定要注意dp的边界问题!坑毁我了 
	for (int j=1;j<=k;j++)f[0][j]=INF;
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=k;j++)
	 if (i>1)f[i][j]=min(f[i-1][j],f[i-2][j-1]+a[i]-a[i-1]);
	 else f[i][j]=f[i-1][j];
	printf("%d",f[n][k]);
	return 0;
}
++++++++++++++++++++++++++++++++++++++

为了ac这道题,作者从网上找了ac的题解,大概有两种做法——贪心和网络流

由于作者不会写网络流所以下面主要介绍贪心的方法,日后,网络流的做法将会更新。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值