石子合併 不同複雜度的做法

2021-07-15 15:07:02 字數 2573 閱讀 4466

n堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將n堆石子合併成一堆的最小代價。

例如: 1 2 3 4,有不少合併方法

1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)

1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)

1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)

括號裡面為總代價可以看出,第一種方法的代價最低,現在給出n堆石子的數量,計算最小合併代價。

當n小於1000的時候可以用樸素的區間dp暴力a之

#include#define maxn 1005

using namespace std;

int a[maxn],sum[maxn],dp[maxn][maxn];

int main()

memset(dp,inf,sizeof(dp));

for(int i=1;i<=n;++i)dp[i][i]=0;

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

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

cout《當大於1000的時候可以採用四邊形不等式優化讓複雜度降到n*n 這裡51nod的1022題 

n堆石子擺成乙個環。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的代價。計算將n堆石子合併成一堆的最小代價。

例如: 1 2 3 4,有不少合併方法

1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)

1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)

1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)

括號裡面為總代價可以看出,第一種方法的代價最低,現在給出n堆石子的數量,計算最小合併代價。

利用四邊形不等式進行優化

#includeusing namespace std;

#define n 2009

int n,f[n][n]=,a[n][n]=;

int s[n][n];

int main()}}

}int ans = f[0][n-1];

for(int i=1;if[i][i+n-1])

ans = f[i][i+n-1];

printf("%d\n",ans);

return 0;

}

最後當n特別大的時候比如5w,這時候採用 garsiawachs演算法

設序列是stone

,從左往右,找乙個滿足

stone[

k-1] <= 

stone[

k+1]的k

,找到後合併

stone[k]

和stone[

k-1]

,再從當前位置開始向左找最大的

j,使其滿足

stone[j] > 

stone[k]

+stone[k-1]

,插到j

的後面就行。一直重複,直到只剩下一堆石子就可以了。在這個過程中,可以假設

stone[-1]

和stone[n]

是正無窮的。

舉個例子:

186 64 35 32 103

因為35<103,所以最小的k是3,我們先把35和32刪除,得到他們的和67,並向前尋找乙個第乙個超過67的數,把67插入到他後面,得到:186 67 64 103,現在由5個數變為4個數了,繼續:186 131 103,現在k=2(別忘了,設a[-1]和a[n]等於正無窮大)234 186,最後得到420。最後的答案呢?就是各次合併的重量之和,即420+234+131+67=852。

基本思想是通過樹的最優性得到乙個節點間深度的約束,之後證明操作一次之後的解可以和原來的解一一對應,並保證節點移動之後他所在的深度不會改變。具體實現這個演算法需要一點技巧,精髓在於不停快速尋找最小的k,即維護乙個「2-遞減序列」樸素的實現的時間複雜度是o(n*n),但可以用乙個平衡樹來優化,使得最終複雜度為o(nlogn)。

#include #include #include #define maxn 55555

using namespace std;

int a[maxn];

int t;

long long ans;

void doit(int x)

}int main()

while(t>1)doit(t-1);

cout<}

return 0;

演算法的複雜度 時間複雜度與空間複雜度

通常,對於乙個給定的演算法,我們要做 兩項分析。第一是從數學上證明演算法的正確性,這一步主要用到形式化證明的方法及相關推理模式,如迴圈不變式 數學歸納法等。而在證明演算法是正確的基礎上,第二步就是分析演算法的時間複雜度。演算法的時間複雜度反映了程式執行時間隨輸入規模增長而增長的量級,在很大程度上能很...

合併時間區間(時間複雜度 O n )

給定乙個按開始時間從小到大排序的時間區間集合,請將重疊的區間合併。時間區間集合用乙個二維陣列表示,二維陣列的每一行表示乙個時間區間 閉區間 其中 0 位置元素表示時間區間開始,1位置元素表示時間區間結束。例 1 輸入 1,3 2,6 8,10 15,18 返回 1,6 8,10 15,18 解釋 時...

演算法的複雜度 演算法的時間複雜度和空間複雜度

在一次筆試題目中,發現了自己對於演算法的時間複雜度問題上並沒有完全清晰這個概念和計算方法,故上網尋找到比較好的詳細介紹來學習。演算法的時間複雜度和空間複雜度合稱為演算法的複雜度。1.時間複雜度 1 時間頻度 乙個演算法執行所耗費的時間,從理論上是不能算出來的,必須上機執行測試才能知道。但我們不可能也...