動態規劃法求解RMQ

2021-05-17 14:18:55 字數 1695 閱讀 7100

題目描述:

思路分析:

下面把sparse table演算法分成預處理和查詢兩部分來說明(以求最小值為例)。

預處理:

預處理使用dp的思想,f(i, j)表示[i, i+2^j - 1]區間中的最小值,我們可以開闢乙個陣列專門來儲存f(i, j)的值。

例如,f(0, 0)表示[0,0]之間的最小值,就是num[0], f(0, 2)表示[0, 3]之間的最小值, f(2, 4)表示[2, 17]之間的最小值

注意, 因為f(i, j)可以由f(i, j - 1)和f(i+2^(j-1), j-1)匯出, 而遞推的初值(所有的f(i, 0) = i)都是已知的

所以我們可以採用自底向上的演算法遞推地給出所有符合條件的f(i, j)的值。

查詢:假設要查詢從m到n這一段的最小值, 那麼我們先求出乙個最大的k, 使得k滿足2^k <= (n - m + 1).

於是我們就可以把[m, n]分成兩個(部分重疊的)長度為2^k的區間: [m, m+2^k-1], [n-2^k+1, n];

而我們之前已經求出了f(m, k)為[m, m+2^k-1]的最小值, f(n-2^k+1, k)為[n-2^k+1, n]的最小值

我們只要返回其中更小的那個, 就是我們想要的答案, 這個演算法的時間複雜度是o(1)的.

例如, rmq(0, 11) = min(f(0, 3), f(4, 3))

**:#include

#include

using namespace std;

#define maxn   10000

#define mmin(seq, a, b)  ((seq[a] < seq[b]) ? (a) : (b))

dp status

int fij[maxn][100];

for output fij

template

void dp_st_print(t seq, int n)}}

// 查詢:

// 假設要查詢從m到n這一段的最小值, 那麼我們先求出乙個最大的k,

// 使得k滿足2^k <= (n - m + 1).於是我們就可以把[m, n]分成

// 兩個(部分重疊的)長度為2^k的區間: [m, m+2^k-1], [n-2^k+1, n];

// 而我們之前已經求出了f(m, k)為[m, m+2^k-1]的最小值, f(n-2^k+1, k)

// 為[n-2^k+1, n]的最小值,我們只要返回其中更小的那個,

// 就是我們想要的答案, 這個演算法的時間複雜度是o(1)的.

// 例如, rmq(0, 11) = min(f(0, 3), f(4, 3))

template

void rmq(t seq, int i, int j)

;st(a, 12);

dp_st_print(a, 12);

rmq(a, 0, 2);

rmq(a, 5, 11);

int b = ;

st(b, 12);

dp_st_print(b, 12);

rmq(b, 0, 2);

rmq(b, 7, 11);

system("pause");

return 0;

}

動態規劃法

在學習動態規劃法之前,我們先來了解動態規劃的幾個概念 1 階段 把問題分成幾個相互聯絡的有順序的幾個環節,這些環節即稱為階段。2 狀態 某一階段的出發位置稱為狀態。3 決策 從某階段的乙個狀態演變到下乙個階段某狀態的選擇。4 狀態轉移方程 前一階段的終點就是後一階段的起點,前一階段的決策選擇匯出了後...

動態規劃法

有些問題在分解時會產生許多子問題,且分解出的自問題互相交織,因而在解這類問題時,將可能重複多次解乙個子問題。這種重複當然是不必要的,解決方法可以在解決每個子問題後把它的解 包括其子子問題的解 保留在乙個 中,若遇到求與之相同的子問題時,dp演算法又稱動態規劃,是資訊學競賽中選手必須熟練掌握的一種演算...

動態規劃法

最近遇到了一道挺有意思的演算法題 四種硬幣 1元3元4元5元 問 想要湊成n元錢最少幾枚硬幣?public class coinsgamemain fun 7,is public static void fun int k,int is i1 l min i2 if l k private stat...