Codevs1615資料備份

2021-08-10 12:08:36 字數 3624 閱讀 8495

思路:

方案一:o(n*k)的dp…只能得部分分。

首先我們知道,只選擇相鄰的點構成線段,答案一定不會變差。

因為若選擇跨點連線,我們必然可以用其中相鄰點構成的連線代替,且使得權值更小。

那麼我們就只考慮相鄰點構成的線段如何選取。

我們設dp[i][j][1/0]前i條線段選了j條線段是否選擇當前線段(包括在j內)

每次用前一條線段的狀態更新當前線段選取狀態即可。

注意:若我們選擇了一條線段,那麼這條線段兩邊的線段都不可選,這個限制條件是我們更新的前提。

**——dp版本

#include

#include

#include

#include

#include

using

namespace

std;

int n,k;

int pos[100010],dis[100010];

int dp[1010][1010][2];//dp[i][j][1/0]前i條線段選了j條線段是否選擇當前線段(包括在j內)

int main() //1--選 0--不選

}printf("%d",min(dp[n-1][k][0],dp[n-1][k][1]));

return

0;}

方案二:貪心有點類似於之前一次互測的problem 3

基本思路:維護乙個小根堆,堆中存所有線段,每次取出權值最小的線段加入答案。

顯然有反例。

那麼我們就在每次取出權值最小的線段後,將其左右兩邊線段的權值x1,x2相加再減去當前線段權值y1,並將x1+x2-y1加入堆中。

這樣,若x1 + x2 - y1的值比堆中其他元素大,我們就不會選擇x1,x2的方案。因為選擇x1 + x2的方案一定不如當前選了y1,再在堆中選擇權值y2盡量小的乙個元素的方案優。即 x1 + x2 - y1 > y2,則x1 + x2 > y1+ y2,選擇x1,x2的方案不符合我們權值盡量小的要求。

若x1 + x2 - y1的值比堆中其他元素小,我們就會取出x1 + x2 - y1,並讓ans + x1 + x2 - y1,因為ans原本就加過y1,一加一減ans中就只剩下了x1和x2,即選擇了x1,x2的方案而不選擇y1,y2。因為選擇x1 + x2的方案一定比當前選了y1,再在堆中選擇權值y2盡量小的乙個元素的方案優。即 x1 + x2 - y1 < y2,則x1 + x2 < y1+ y2,選擇x1,x2的方案符合我們權值盡量小的要求。

由於單選一條線段會使選擇線段數+1,而選擇兩條線段會先使選擇線段數-1,再使其+2,不會存在超過k的情況。

另外 還有一些細節處理:

我們需要建立used陣列保證我們在選擇一條線段後,不會單獨選擇其相鄰的線段。

每次僅會取出used為0的線段。

那麼我們又如何記錄x1 + x2 - y1呢?

為了方便處理,我們可以把這個值看作一條線段的值,線段的位置就選y1的位置,used也就相應為0了。

那….還有乙個問題。

我們用y1的位置代表x1 + x2 - y1的位置,那如果成功用選擇x1,x2代替了選擇y1,y2的方案,那麼我們怎麼標記x1左邊,x2右邊的線段不可用(used=1)啊?(y1位置不用考慮,因為堆中已經沒有y1對應線段了,同理如下)。

鍊錶!

用鍊錶維護線段相鄰關係,每次取一條線段(這裡的線段也表示x1 + x2 - y1對應線段)後,將其前驅與後繼都向後移一位,這樣原本y1連線的前驅後繼就變成了pre[y1]和nxt[y1],下一次若取到x1,x2,直接將其位置的前驅和後繼used設為1即可。

另外,邊界部分即編號為0和n的線段的權值要賦極大值,原因如下:

當且僅當我們在之前選擇了1號線段,才會有0號和2號線段被同時選擇的方案,而這種方案一定是不優的,因為這種情況下2號線段的長度一定比1號線段長,且選擇2號線段還會影響3號線段的選擇,完全可以用1號線段代替2號線段。所以要把0號線段的權值賦極大值防止這種方案被選。

補充一點:需要注意的是,取到x1,x2的線段後,我們會把pre[x1] - nxt[x2] - x1 - x2 + y1壓入堆中,即選擇y1,不選x1,x2,選擇x1前一條線段,選擇x2後一條線段的方案。對答案的影響如之前所述。關於這個操作的實現,還需要在每次取出一條線段後,更新其dis值為前驅dis值+後繼dis值-當前dis值,**實現比較精明請仔細體會。

**——貪心版本

#include

#include

#include

#include

#include

#include

using

namespace

std;

int n,k,ans;

int pos[1000010],dis[1000010];

int pre[1000010],nxt[1000010];

bool used[1000010];

struct ini

;ini u;

bool

operator

< (ini a,ini b)

priority_queueq;

int main()

); pre[i]=i-1;

nxt[i]=i+1;

}dis[0]=dis[n]=1e9;

pre[0]=n+1,nxt[n]=1;

/*for(int i=2;i<=n;i++)

);pre[i]=i-1;

nxt[i]=i+1;

}dis[1]=dis[n+1]=1e9;

pre[1]=n+1,nxt[n+1]=1;

*/for(int i=1;i<=k;i++)

);dis[k.a]=dis[pre[k.a]]+dis[nxt[k.a]]-dis[k.a];

used[pre[k.a]]=used[nxt[k.a]]=1;

pre[k.a]=pre[pre[k.a]],nxt[k.a]=nxt[nxt[k.a]];

nxt[pre[k.a]]=k.a,pre[nxt[k.a]]=k.a;

}printf("%d",ans);

return

0;}

我還是畫一下圖簡述演算法過程吧:

如圖若格仔長度藍色《紅色《黑色,那麼我們會先取出藍色,再取出紅色部分作為答案,再取出黑色+藍色部分作為答案。

codevs 1615 資料備份

題目描述 description 你在一家it 公司為大型寫字樓或辦公樓 offices 的計算機資料做備份。然而資料備份的工作是枯燥乏味的,因此你想設計乙個系統讓不同的辦公樓彼此 之間互相備份,而你則坐在家中盡享計算機遊戲的樂趣。已知辦公樓都位於同一條街上。你決定給這些辦公樓配對 兩個一組 每 一...

資料備份 Trilium 本地資料備份同步

預設的資料儲存位置 document.db 裡面包含了所有的筆記內容 config.ini 是軟體相關的設定,可以設定使用的埠,但是這個是歸屬於環境變數下面的,導致暫時不知道怎麼同時執行2個trilium backup 裡面是軟體自動備份的資料庫 log 日誌檔案 here s how the lo...

資料副本管理 資料完全備份 差異備份 增量備份介紹

為避免因自然災害等意外情況而導致的本地資料丟失情況,異地資料容災也是企業資料保護的一大常見命題。ucahe備份呢支援通過遠端複製技術,將本地資料同步到異地,實現異地資料保護。一站式的web管理,支援增量 差異,永久,定時,多副本等30多項功能列表,8項災備技術,3款產品,滿足企業不同場景的資料備份需...