題目描述:
思路分析:
下面把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...