數據備份 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的題解,大概有兩種做法——貪心和網絡流
由於作者不會寫網絡流所以下面主要介紹貪心的方法,日後,網絡流的做法將會更新。