藍橋杯/nyoj 737 合併石子 區間dp+平行四邊形優化
接下來一行,包含n個整數,按順序給出每堆石子的大小 。 輸出格式 輸出一個整數,表示合併的最小花費。 樣例輸入 5
1 2 3 4 5 樣例輸出 33 資料規模和約定
1<=n<=1000, 每堆石子至少1顆,最多10000顆。
思路:
第一個區間dp的題,一開始還以為是貪心。。。結果不是 貪心演算法在子過程中得出的解只是區域性最優,而不能保證使得全域性的值最優。
這個題就是三層的for迴圈
最外面一層表示區間的長度 因為自己一堆時長度為1不合並 所以len從2到n
第二層列舉的起點位置,i從1到n-len+1,通過起點位置和區間長度計算出終止點位置j=i+len-1
第三層 知道起始位置和末位置,我們來 列舉合併斷開的位置 k從i到j-1 從而通過一個個子問題找到最優解
動態轉移方程
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]);
結果在藍橋杯上超時了..應該把min函式去掉在優化一下會卡線過吧
90分程式碼
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int maxn=1111; int dp[maxn][maxn],sum[maxn]; int a[maxn]; int main() { int i,n,j,k,len; while(~scanf("%d",&n)) { memset(sum,0,sizeof(sum)); for(i=1;i<=n;i++) { dp[i][i]=0; scanf("%d",&a[i]); sum[i]+=sum[i-1]+a[i]; } for(len=2;len<=n;len++) { for(i=1;i<=n-len+1;i++) { j=i+len-1; dp[i][j]=inf; for(k=i;k<=j-1;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); } } printf("%d\n",dp[1][n]); } return 0; }
網上學了一下 這個題需要用到一個平行四邊形優化
具體證明看這裡。。反正我是沒看懂,感覺就是加了一個 s[i][[j記錄dp[i][j]之間的一個最優分割點 就把k限定在了 s[i][j-1]...s[i+1][j]之間。至於為啥我也是似懂非懂
可以優化到30 -40ms
#include<bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; const int maxn=1111; int a[maxn],dp[maxn][maxn],sum[maxn],s[maxn][maxn]; int main() { int i,j,k,len,n; while(scanf("%d",&n)!=EOF) { memset(sum,0,sizeof(sum)); memset(dp,0,sizeof(dp)); memset(s,0,sizeof(s)); for(i=1;i<=n;i++) { scanf("%d",&a[i]); s[i][i]=i; dp[i][i]=0; sum[i]+=sum[i-1]+a[i]; } for(len=2;len<=n;len++) { for(i=1;i<=n-len+1;i++) { j=i+len-1; dp[i][j]=inf; for(k=s[i][j-1];k<=s[i+1][j];k++) { if(dp[i][j]>dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]) { dp[i][j]=dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]; s[i][j]=k; } } } } printf("%d\n",dp[1][n]); } return 0; }
相關推薦
藍橋杯/nyoj 737 合併石子 區間dp+平行四邊形優化
問題描述 在一條直線上有n堆石子,每堆有一定的數量,每次可以將兩堆相鄰的石子合併,合併後放在兩堆的中間位置,合併的費用為兩堆石子的總數。求把所有石子合併成一堆的最小花費。 輸入格式 輸入第一行包含一個整數n,表示石子的堆數。 接下來一行,包含n個整數,按
HDU3480_區間DP平行四邊形優化
做到現在能一眼看出來是區間DP的問題了 也能夠知道dp[i][j]表示前 i 個節點被分為 j 個區間所取得的最優值的情況 cost[i][j]表示從i到j元素區間中的值,這裡可以直接排序後簡單求出——也就是我們的代價函式 這樣其實就能夠做出來了,但是空間複
藍橋杯訓練:合併石子
問題描述 在一條直線上有n堆石子,每堆有一定的數量,每次可以將兩堆相鄰的石子合併,合併後放在兩堆的中間位置,合併的費用為兩堆石子的總數。求把所有石子合併成一堆的最小花費。 輸入格式 輸入第一行包含一個整數n,表示石子的堆數。 接下來一行,包含
[NOI1995]石子合併(區間DP)
題目連結: [NOI1995]石子合併 思路: 區間DP經典例題,可以把前n-1堆石子一個個移到第n個後面,那樣環就變成了線,即現在有2*n-1堆石子需要合併。 程式碼: #include <iostream> #include
石子合併 (區間DP)
一.試題在一個園形操場的四周擺放N堆石子(N≤100),現要將石子有次序地合併成一堆。規定每次只能選相鄰的兩堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。編一程式,由檔案讀入堆數N及每堆的石子數(≤20),①選擇一種合併石子的方案,使得做N-1次合併,得分
石子合併【區間dp】
有N堆石子排成一排,每堆石子有一定的數量。現要將N堆石子併成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過N-1次合併後成為一堆。求出總的代價最小值
石子合併(一) 區間DP
石子合併(一)(傳送門) 時間限制:1000 ms | 記憶體限制:65535 KB 難度:3 描述 有N堆石子排成一排,每堆石子有一定的數量。現要將N堆石子併成為一堆。合併的過程只
第四屆藍橋杯真題 連號區間
max 排列 add sca ace box 題目 initial for 本來想練習並查集,然後在看官網提示這是並查集類型題目,上來先默寫了一下並查集,想了半天並查集怎麽寫。。我呸,並查集。。這裏找規律。。區間的【最大值-最小值】=【區間長度】,直接枚舉。。。討厭這種找規
藍橋杯歷屆試題 連號區間數:枚舉(含樣例解釋)
簡單 表示 main 排列 定義 head clas 單個 ace 問題描述 小明這些天一直在思考這樣一個奇怪而有趣的問題: 在1~N的某個全排列中有多少個連號區間呢?這裏所說的連號區間的定義是: 如果區間[L, R] 裏的所有元素(即此排列的第L個到第R個元
區間dp 與 四邊形不等式優化 學習筆記
部落格目錄 很久之前在網上看了傳說中的四邊形不等式,然後現在發現忘光了。趁比賽前夕趕快拿來熟悉一下。 一、引入 形如: dp[i][j]=min{dp[i][k]+dp[k+1][j]+cost[i][j]} 的狀態轉移方程,如果不加優化的話ijk三層迴圈O(n
DP的平行四邊形優化
Luogu P4767 [IOI2000]郵局 #include <bits/stdc++.h> using namespace std; int n,m,a[3005],mk[3005][
論區間動態規劃——平行四邊形優化
區間動態規劃: 針對區間問題的最優解而產生的一種動態規劃演算法,通常以區間為狀態來記錄最優解,故狀態為O(N^2) 而轉移則是列舉這段區間中的決策點,通過兩個更小的區間最優解得合併來得到這段區間的狀態,故轉移為(N) 則狀態O(N^2),轉移O(N),總時間
用一題來說明dp平行四邊優化
poj 1160 題意:給出n個村莊,村莊是一條直線排好的,並且給出每個村莊到直線最左邊初始點的距離。現在要建立m個郵局,於是引入一個距離S{各個村莊到最近的郵局的距離和}。那麼現在問題來了如何使得這個S的值最小? 題解:定義這樣的方程 dp[i][j] = min{ d
nyoj 737 石子合併(一) 【區間dp】
石子合併(一) 時間限制:1000 ms | 記憶體限制:65535 KB 難度:3 描述 有N堆石子排成一排,每堆石子有一定的數量。現要將N堆石子併成為一堆。合併的過程只能每次
NYOJ 737 石子合併(一)(區間dp)
石子合併(一) 時間限制:1000 ms | 記憶體限制:65535 KB 難度:3 描述 有N堆石子排成一排,每堆石子有一定的數量。現要將N堆石子併成為一堆。合併的過程只能每次將相鄰的兩堆石子堆成一堆,每次合併花費的代價為這兩堆石子的和,經過N-1次合
NYOJ題目737石子合併(一)(區間dp)
石子合併(一) 時間限制:1000 ms | 記憶體限制:65535 KB 難度:3 描述 有N堆石子排成一排,每堆石子有一定的數量。現要將N堆石子併成為一堆。合併的過程只能每次將
nyoj 737 石子合並(區間DP)
using lac padding gin height space outline style 每次 737-石子合並(一) 內存限制:64MB 時間限制:1000ms 特判: No通過數:28 提交數:35 難度:3 題目描
藍橋杯 合併石子 DP+四邊形不等式優化
演算法提高 合併石子 時間限制:2.0s 記憶體限制:256.0MB 問題描述 在一條直線上有n堆石子,每堆有一定的數量,每次可以將兩堆相鄰的石子合併,合併後放在兩堆
藍橋杯 —— 石子合併問題 —— Dp
題目大意是說給你一個n,代表有n堆石子。然後給你n個數,分別表示每堆石子的個數。 要求是每次只能合併相鄰的兩堆石子,每合併一次就把ans += 需要被合併的兩堆石子的個數。 問怎樣合併使得最後所需要的費用 ans 值最小。 解題思路:這道題不能夠用區域性最優的貪心思想
區間DP入門之 石子歸併問題 NYOJ 737
分析:要求n個石子歸併,我們根據dp的思想劃分成子問題,先求出每兩個合併的最小代價,然後每三個的最小代價,依次知道n個。 定義狀態dp [ i ] [ j ]為從第i個石子到第j個石子的合併最小代