石子合并问题java,石子合并问题 GarsiaWachs算法
石子合并問題 GarsiaWachs算法
目錄引入
一個較為樸素的算法
GarsiaWachs算法
引入
在一個操場上擺放著一排 \(N\) 堆石子。現要將石子有次序地合并成一堆。規定每次只能選相鄰的 \(2\) 堆石子合并成新的一堆,并將新的一堆石子數記為該次合并的得分。
試設計一個算法,計算出將 \(N\) 堆石子合并成一堆的最小得分。
數據范圍 \(n \le 4e4\)
一個較為樸素的算法
不是暴力
按照區間DP的思路來做
設 \(f_{i, j}\) 表示區間 \([i, j]\) 合并的最小得分,枚舉一個端點 \(k\),那么有轉移方程:(其中 \(a\) 數組是預處理后的前綴和)
\[f_{i, j} = \min \{ f_{i, j}, f_{i, k} + f_{k + 1, j} + a_j - a_{i - 1} \}
\]
注意 \(i\) 要倒序枚舉,\(j\) 要正序枚舉
答案就是 \(f_{1, n}\)
時間復雜度: \(O(n^3)\);空間復雜度:\(O(n^2)\)
Code
/*
Work by: Suzt_ilymics
Knowledge:
Time: O()
*/
#includeiostream
#includecstdio
#includecstring
#includealgorithm
#define LL long long
#define orz cout"lkp AK IOI!"endl
using namespace std;
const int MAXN = 22335;
const int INF = 1e9+7;
const int mod = 1e9+7;
int n;
int a[MAXN];
int f[MAXN][MAXN];
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s 1) + (s 3) + ch - '0' , ch = getchar();
return f -s : s;
}
int main()
{
n = read();
for(int i = 1; i = n; ++i) a[i] = read() + a[i - 1];
for(int i = n; i = 1; --i){
for(int j = i; j = n; ++j){
if(i == j) continue;
f[i][j] = INF;
for(int k = i; k j; ++k) f[i][j] = min(f[i][j], f[i][k] + f[k + 1][j] + a[j] - a[i - 1]);
}
}
printf("%d\n", f[1][n]);
return 0;
}
GarsiaWachs算法
發現數據范圍太大了,上面的算法已經不能滿足我們的需求,這里有一種優化算法,專門用來解決石子問題
每次操作,從前向后找一個最小的 \(k\),使其滿足 \(a_{k - 1} \le a_{k + 1}\),然后合并 \(a_{k - 1}\) 和 \(a_k\)
從 \(k\) 開始向前找到第一個 \(j\) 使得 \(a_j a_{k - 1} + a_k\),并將合并后的新值插入位置 \(j\) 后面
進行 \(n - 1\) 次結束,在合并過程中統計答案即可
時間復雜度:\(O(n^2)\);空間復雜度:\(O(n)\)
正確性證明:作為一個OI,會應用就好啦,其實是我不會
Code
/*
Work by: Suzt_ilymics
Knowledge:
Time: O()
*/
#includeiostream
#includecstdio
#includecstring
#includealgorithm
#includevector
#define LL long long
#define orz cout"lkp AK IOI!"endl
using namespace std;
const int MAXN = 1e5+5;
const int INF = 1e9+7;
const int mod = 1e9+7;
LL n, ans = 0;
vectorint a;
int read(){
int s = 0, f = 0;
char ch = getchar();
while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
while(isdigit(ch)) s = (s 1) + (s 3) + ch - '0' , ch = getchar();
return f -s : s;
}
int merge(){//GarsiaWachs算法
int k = a.size() - 2;
for(int i = 0; i a.size() - 2; ++i)
if(a[i] = a[i + 2]){
k = i; break;
}
int sum = a[k] + a[k + 1];
a.erase(a.begin() + k);
a.erase(a.begin() + k);
int inst = -1;
for(int i = k - 1; i = 0; --i)
if(a[i] sum){
inst = i; break;
}
a.insert(a.begin() + inst + 1, sum);
return sum;
}
int main()
{
n = read();
for(int i = 1; i = n; ++i) a.push_back(read());
for(int i = 1; i n; ++i) ans += merge();
printf("%lld", ans);
return 0;
}
石子合并問題 GarsiaWachs算法 相關文章
圖解算法——合并k個排序列表(Merge k Sorted Lists)
1. 題目描述 You are given an array of k linked-lists lists, each linked-list is sorted in ascending order. Merge all the linked-lists into one sorted linked-list and return it. 翻譯: 給定一個 鏈表長度為k 的鏈表 數組 ,每個鏈表按 升序 排序
three.js中,綁定 mouseup 和 mousedown 事件不起作用/使用three.js實現點誰誰變紅,已解決鼠標選不到目標問題
先檢查一下你是否使用了 OrbitControls 如果使用了,同時想要添加點擊事件,給物體模型添加點擊事件,例如添加點到誰,誰就紅 代碼如下: // 點擊功能let raycaster = nulllet instersected = nulllet mouse = nulllet useClick = false/** * 打開addClick函
第39天學習打卡(多線程 Thread Runnable 初始并發問題 Callable )
多線程詳解 01線程簡介 Process與Thread 程序:是指令和數據的有序集合,其本身沒有任何運行的含義,是一個靜態的概念。 進程則是執行程序的一次執行過程,它是一個動態的概念。是系統資源分配的單位。 通常在一個進程中可以包含若干個線程,當然一個進程中
Ubuntu下SystemTap的安裝問題解決記錄
SystemTap的安裝方式: 一.直接通過apt-get安裝 sudo apt-get install systemtap 二.通過安裝包下載 $ sudo apt-get install build-essential$ sudo apt-get install gettext$ sudo apt-get install elfutils$ sudo apt-get install libdw-dev$ wget https:/
【劍指Offer-15】二進制中1的個數
問題 請實現一個函數,輸入一個整數(以二進制串形式),輸出該數二進制表示中 1 的個數。例如,把 9表示成二進制是 1001,有 2 位是 1。因此,如果輸入 9,則該函數輸出 2。 示例 輸入: 00000000000000000000000000001011 輸出: 3 解釋: 輸入的二進制串
C++求快速冪
“快速冪”被歸結為一個a的b次方對m取余的問題,即 a b % m 問題的關鍵在于怎么更快地求得a b ,直觀的做法是用b次循環去累乘a,時間復雜度是O(b)。而“快速冪”,又成為“二分冪”,通過二分的思想能在O(log b )的復雜度內求得a b 。 如果次數b是奇數,則a
01背包問題理解動態規劃算法
一.動態規劃算法 簡單理解:在一些分治算法解決的問題中,需要將較大規模的問題轉化為較小規模的問題,往往會用到遞歸。但是在一些問題中,遞歸的小問題被多次重復運算,浪費了性能,因此可以使用數組或者其他合適的方式將運算過的小規模問題的結果記錄下來
使用Python批量合并文件夾下.csv數據
實現目標:一個文件夾下包括n個.csv數據文件,想將后綴為ts.csv的文件與對應數字的.csv文件進行合并 此圖為wf.csv文件中的數據格式,ts.csv文件是與此文件等行數的一列數據,將此列數據添加到已有18列數據的后面,完成數據合并操作 代碼如下: import pandas
【劍指Offer-13】機器人的運動范圍
問題 地上有一個m行n列的方格,從坐標 [0,0] 到坐標 [m-1,n-1] 。一個機器人從坐標 [0, 0] 的格子開始移動,它每次可以向左、右、上、下移動一格(不能移動到方格外),也不能進入行坐標和列坐標的數位之和大于k的格子。例如,當k為18時,機器人能夠進入方格
類似jar文件使用java無法打開問題
## 原因我一個彩筆在ctfhub,想對圖片進行分割,拼接等操作,需要用到**Stegsolve**但是安裝了java環境的我無法打開,經過校友的3、4次卸載安裝還是沒有讓這個文件打開。。。(當然選擇了正確的應用程序打開方式,環境變量也試了,就是打不開)命令窗口輸入j
總結
以上是生活随笔為你收集整理的石子合并问题java,石子合并问题 GarsiaWachs算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IBM宣布退出俄罗斯市场:已暂停在俄所有
- 下一篇: 小米首款徕卡旗舰正在路上:雷军晒72年前