ACM第一次集訓 動態規劃問題

2021-08-18 19:59:41 字數 4045 閱讀 4858

2018-4-15

1.石子合併問題

1)設有n堆沙子排成一排,其編號為1,2,3,…,n(n<=100)。每堆沙子有一定的數量。現要將n堆沙子並成為一堆。歸併的過程每次將任意兩堆沙子堆成一堆(每次合併花費的代價為當前兩堆沙子的總數量),這樣經過n-1次歸併後成為一堆,歸併的總代價為每次合併花費的代價和。找出一種合理的歸併方法,使總的代價最小。

我們可以使用貪心演算法,每次只合併兩個數量最小的沙子,所得到的結果就是最優解了。

其實這就是哈夫曼編碼的變形。

每一次都要進行排序,雖然有點智障,但是還是寫了…(注釋的地方),

我的想法是每次將合併過後的值插入到它合適的位置,使得剩下的還是有序的即可。

#include

#include

using

namespace

std;

const

int n = 100;

int x[n+1];

int n;

int main()

sort(x,x+n);

// for (i=1;i

// sum+=x[i]+x[i-1];

// x[i]=x[i]+x[i-1];

// sort(x+i,x+n);

// }

for (i=1;iint tmp=x[i]+x[i-1];

sum+=tmp;

j=i+1;

while (tmp>x[j]&&j1]=x[j];

j++;

}x[j-1]=tmp;

}cout

0;}

2)倘若我們每次只能合併相鄰的兩個石子呢?

貪心這個時候就不可以了,因為我們無法保證全域性最優,雖然不對,但是我還是寫了…

#include

#include

#define inf 0x3f3f3f3f

using

namespace

std;

int n;

int main()

int cnt=0;

for (int i=0;i1;i++)

}cnt+=tmp;

vec.erase(vec.begin()+k);

vec.erase(vec.begin()+k-1);

vec.insert(vec.begin()+k-1,tmp);

}

cout

0;}

其實正確的解法應該是用動態規劃求解:

#include

using

namespace

std;

const

int n = 1000;

int x[n+1],dp[n+1][n+1],s[n+1];

int n;

int main()

for (int l=2;l<=n;l++)}}

// for (int i=1;i<=n;i++)

// coutcout

<1][n]0;}

3)其實最終的題目應該是我們的這個沙子堆是環形的!

其實對於環形問題我們之前有過涉及,就是在直線後面再補充那麼多就可以了!就是與usaco裡面的那個項鍊問題差不多!

#include

using

namespace

std;

const

int n = 2000;

int x[n+1],dp[n+1][n+1],s[n+1];

int n;

int main()

for (int i=1;i<=n;i++)

for (int l=2;l<=n;l++)

dp[i][j]+=s[j]-s[i]+x[i];}}

int res=n;

for (int i=1;i<=n;i++)

cout

0;}

2.整數劃分問題

自行車選手在訓練時,需要圍繞著場地騎行n圈。給了使得訓練有效,可以一次把n全部騎完,

也可以分成若干次完成,但每次都比上一次騎的圈數要多,那麼完成一次訓練即騎完n圈,

有多種訓練方式

樣例輸入

6樣例輸出

4//例如,當 n = 6 時,有以下四種訓練方案:

6 1 2 3

1 5

2 4這個題目其實就是乙個整數劃分問題,整數劃分又分為好多種:

1)將n劃分成若干正整數之和的劃分數

其實這是乙個方蘋果的問題,假設f(n,m)表示將n個蘋果放在m個籃子裡面,那麼我們一共有兩種情況:如果n>m的話,我們一定會有空的籃子,也就是等同於f(m,m),反之n

#include

using

namespace

std;

int n,cnt;

void dfs(int sum,int pre)

for (int i=pre;i<=n;i++)

}int main()

實際上應該是用動態規劃問題…

3.最長不下降子串行問題

若干人排成一行,且身高分別為b1,b2,…,bn。準備從中選出一組滿足身高不降的人組成一隊。

例如13,7,9,16,38,24,37,18,44,19,21,22,63,15。

有13<16<38<44<63 長度為5的不下降子串行。

但經過觀察,實際還有7<9<16<18<19<21<22<63 長度為8的不下降子串行。

給出最長佇列的長度。

【輸入格式】

第一行為n,表示n(n≤100000)個數。第二行為n個數的值。

【輸出格式】

乙個整數。

【輸入樣例】

1 3 1 2

【輸出樣例】

簡單的動態規劃問題:

#include

using

namespace

std;

const

int n = 100000;

int x[n+1],dp[n+1];

int n;

int main()

for (int i=1;i<=n;i++)}}

int res=0;

for (int i=1;i<=n;i++)

cout

0;}

4.最長不下降子串行的公升級問題

為了外來飛彈襲擊,最新的飛彈攔截系統已經研製好了.但是這種飛彈攔截系統有乙個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。

某天,雷達捕捉到了飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。

輸入飛彈依次飛來的高度(雷達給出的高度資料是不大於30000 的正整數),計算這套系統最多能攔截多少飛彈和如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。

【輸入樣例】

389 207 155 300 299 170 158 65

【輸出樣例】

6(最多能攔截的飛彈數)

2(要攔截所有飛彈最少要配備的系統數)

#include

using

namespace

std;

const

int n = 100000;

int x[n+1],dp[n+1];

int n;

int main()

n=i;

for (int i=1;i<=n;i++)}}

int res=0;

for (int i=1;i<=n;i++)

cout}}

res=0;

for (int i=1;i<=n;i++)

cout

0;}

這裡需要我們用乙個結論:求…等於最長非遞增子串行。

第一次寫動態規劃

時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 題目描述 有乙個箱子容量為v 正整數,0 v 20000 同時有n個物品 0 n 30 每個物品有乙個體積 正整數 要求n個物品中,任取若干個裝入箱內,使箱子的剩餘...

第一次集訓賽

a misha and changing handles codeforces 501b 簡述 cf上可以改網名,輸入多個新舊網名,輸出有幾個人 以及他們最初的網名和最終的網名 include include includeusing namespace std int main if flag n...

藍橋杯第一次集訓

public class main public class main system.out.println string.format 2f pay 把abcd.s共19個字母組成的序列重複拼接106次,得到長度為2014的串。接下來刪除第1個字母 即開頭的字母a 以及第3個,第5個等所有奇數字置...