week10作業 動態規劃(一)

2021-10-05 11:37:38 字數 4355 閱讀 3771

b - lis & lcs

c-拿數問題 ii

a-簽到題

題目要求

東東在玩遊戲「game23」。

在一開始他有乙個數字n,他的目標是把它轉換成m,在每一步操作中,他可以將n乘以2或乘以3,他可以進行任意次操作。輸出將n轉換成m的操作次數,如果轉換不了輸出-1。

input

輸入的唯一一行包括兩個整數n和m(1<=n<=m<=5*10^8).

output

輸出從n轉換到m的操作次數,否則輸出-1.

求解思路

採用遞迴的方式進行乘2,乘3排列,遞迴終止條件為找到m,或者大於m。

通過p記錄操作的次數,jud記錄是否找到m。

void

func

(int num,

int p)

if(num == m)

func

(num *

2,p+1)

;func

(num *

3,p+1)

;}

最優解性質:

n 轉成 m

動態規劃方程

自底向上(遞推)或帶備忘的自頂向下(記憶化搜尋)方式計算最優值

構造最優解

**

#include

#include

#include

using

namespace std;

int n, m;

bool jud;

int k;

void

func

(int num,

int p)

if(num == m)

func

(num *

2,p+1)

;func

(num *

3,p+1)

;}intmain()

else

}

b - lis & lcs

題目要求

lis:最長遞增序列

lcs:最長公有序列

東東有兩個序列a和b。

他想要知道序列a的lis和序列ab的lcs的長度。

注意,lis為嚴格遞增的,即a1****** input

5 51 3 2 5 4

2 4 3 1 5

****** output

3 2求解思路

lis:

最優解性質:

最長上公升子串行

動態規劃方程

初始化 f1=1

轉移方程 fi = max + 1

自底向上(遞推)或帶備忘的自頂向下(記憶化搜尋)方式計算最優值

採用遞推方式:

通過兩重迴圈更新f陣列的值:

當 j < i && aj < ai 時,ai可以至少為aj + 1,掃瞄a2~ai,滿足 j < i && aj < ai 最大的aj + 1 即為 ai 的值。

for

(int i=

2;i<=n;i++

)for

(int j =

1; j < i; j++)}

}

構造最優解

最優解為 max

ll mx =0;

for(

int i =

1; i <= n; i++)}

return mx;

時間複雜度 o(n^2)

lcs:

最優解性質:

最長公共子串行

動態規劃方程

初始化 f[1][0]= f[0][1]= f[0][0]=0

轉移方程

當 ai==bj時,f[i][j] = f[i-1][j-1]+ 1,否則,f[i][j] = max

自底向上(遞推)或帶備忘的自頂向下(記憶化搜尋)方式計算最優值

採用遞推方式:

通過兩重迴圈更新f陣列的值:

for

(int i=

1;i<=n;i++

)for

(int j =

1; j <= m; j++

)else

}

構造最優解

最優解為 f[n][m]

時間複雜度 o(nm)

**

#include

#include

#include

typedef

long

long ll;

using

namespace std;

ll a[

5005];

ll b[

5005];

ll f[

5005];

ll g[

5005][

5005];

ll n, m;

ll lis()

for(

int i=

2;i<=n;i++

)for

(int j =

1; j < i; j++)}

} ll mx =0;

for(

int i =

1; i <= n; i++)}

return mx;

}ll lcs()

else

}return g[n]

[m];

}int

main()

for(

int i =

1; i <= m; i++

) cout <<

lis(

)<<

" "<<

lcs();

}

c-拿數問題 ii

題目要求

yjq 上完第10周的程式設計思維與實踐後,想到乙個絕妙的主意,他對拿數問題做了一點小修改,使得這道題變成了 拿數問題 ii。

給乙個序列,裡邊有 n 個數,每一步能拿走乙個數,比如拿第 i 個數, ai = x,得到相應的分數 x,但拿掉這個 ai 後,x+1 和 x-1 (如果有 aj = x+1 或 aj = x-1 存在) 就會變得不可拿(但是有 aj = x 的話可以繼續拿這個 x)。求最大分數。

input

第一行包含乙個整數 n (1 ≤ n ≤ 105),表示數字裡的元素的個數

第二行包含n個整數a1, a2, …, an (1 ≤ ai ≤ 105)

output

輸出乙個整數:n你能得到最大分值。

example

input

21 2

output

2input

31 2 3

output

4input

91 2 1 3 2 2 2 2 3

output

10hint

對於第三個樣例:先選任何乙個值為2的元素,最後陣列內剩下4個2。然後4次選擇2,最終得到10分。

求解思路

最優解性質:

能得到的最大分值

動態規劃方程

按照分值

初始化:dp[0] = 0; dp[1] = arr[1];

轉移方程 :dp[i] = max(dp[i - 1], dp[i - 2] + arr[i]*i);

其中arr[i]為大小為i的數的個數,dp[i]為小於i的數可取到的最大分值。

自底向上(遞推)或帶備忘的自頂向下(記憶化搜尋)方式計算最優值

採用遞推方式:

通過一重迴圈更新dp陣列的值

構造最優解

設給出的數字最大值為max

最優解為 dp[max],因為1 ≤ ai ≤ 10^5,所以可以直接取dp[100003]

時間複雜度 o(n)

**

#include

#include

#include

typedef

long

long ll;

using

namespace std;

ll arr[

100005];

ll dp[

100005];

intmain()

for(ll i =

0; i < n; i++

) dp[0]

=0; dp[1]

= arr[1]

;for

(ll i =

2; i <

100005

; i++

) cout << dp[

100003];

}

week10 作業 動態規劃(一)

東東在玩遊戲 game23 在一開始他有乙個數字n,他的目標是把它轉換成m,在每一步操作中,他可以將n乘以2或乘以3,他可以進行任意次操作。輸出將n轉換成m的操作次數,如果轉換不了輸出 1。輸入的唯一一行包括兩個整數n和m 1 n m 5 10 8 輸出從n轉換到m的操作次數,否則輸出 1.120 ...

week10 作業(動態規劃1)

問題分析 心得體會 b lis lcs 問題分析 心得體會 c 拿數問題 ii 問題分析 心得體會 題目簡述 東東在玩遊戲 game23 在一開始他有乙個數字n,他的目標是把它轉換成m,在每一步操作中,他可以將n乘以2或乘以3,他可以進行任意次操作。輸出將n轉換成m的操作次數,如果轉換不了輸出 1。...

week10作業簽到

東東在玩遊戲 game23 在一開始他有乙個數字n,他的目標是把它轉換成m,在每一步操作中,他可以將n乘以2或乘以3,他可以進行任意次操作。輸出將n轉換成m的操作次數,如果轉換不了輸出 1。輸入的唯一一行包括兩個整數n和m 1 n m 5 10 8 輸出從n轉換到m的操作次數,否則輸出 1.samp...