【动态规划】石子合并 (ssl 2863)
生活随笔
收集整理的這篇文章主要介紹了
【动态规划】石子合并 (ssl 2863)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
石子合并石子合并石子合并
Description
在一個(gè)操場(chǎng)上一排地?cái)[放著N堆石子。現(xiàn)要將石子有次序地合并成一堆。規(guī)定每次只能選相鄰的2堆石子合并成新的一堆,并將新的一堆石子數(shù)記為該次合并的得分。請(qǐng)?jiān)O(shè)計(jì)一個(gè)程序,計(jì)算出將N堆石子合并成一堆的最小得分。
Input
每組數(shù)據(jù)第1行為一個(gè)正整數(shù)N(2<=N<=100),以下N行,每行一個(gè)正整數(shù),小于10000,分別表示第i堆石子的個(gè)數(shù)(1<=i<=N)。
Output
對(duì)于每組數(shù)據(jù)輸出一個(gè)正整數(shù),即最小得分
Sample Input
7
13
7
8
16
21
4
18
Sample Output
239
說明:
本題之前用兩個(gè)方法做過,這次用三個(gè)方法做
方法一方法一方法一
先枚舉前面的數(shù)(i),再枚舉后面的數(shù)(j),最后枚舉中間的分割線(c)(三重循環(huán)) 用i到c-1之間的數(shù)加上c到j(luò)的數(shù)再加上之前的得分,再將所有的值去最小。(計(jì)算一個(gè)數(shù)到另一個(gè)數(shù)可以用前綴和搞定)
狀態(tài)轉(zhuǎn)移方程:
f[i][j]=min(f[i][j],f[i][c?1]+f[c][j]+s[j]?s[i?1])f[i][j]=min(f[i][j],f[i][c-1]+f[c][j]+s[j]-s[i-1])f[i][j]=min(f[i][j],f[i][c?1]+f[c][j]+s[j]?s[i?1])
f[i][j]表示合成i到j(luò)的最小得分
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int n,s[101],f[101][101],x; int main() {memset(f,127/3,sizeof(f));//因?yàn)橐プ钚〉?#xff0c;所以要先賦一個(gè)大的值scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d",&x);s[i]=s[i-1]+x;//前綴和f[i][i]=0;//清零單個(gè)的}for (int i=n-1;i>=1;i--)for (int j=i+1;j<=n;j++)for (int c=i+1;c<=j;c++)f[i][j]=min(f[i][j],f[i][c-1]+f[c][j]+s[j]-s[i-1]);printf("%d",f[1][n]); }方法二方法二方法二
先枚舉長(zhǎng)度(k),再枚舉前面的數(shù)(i),最后枚舉分割線(c),然后后面的數(shù)(j)就可以求出來了:
j=i+k?1j=i+k-1j=i+k?1
之后的步驟和方法一 幾乎 完全一樣
狀態(tài)轉(zhuǎn)移方程:
f[i][j]=min(f[i][j],f[i][c?1]+f[c][j]+s[j]?s[i?1])f[i][j]=min(f[i][j],f[i][c-1]+f[c][j]+s[j]-s[i-1])f[i][j]=min(f[i][j],f[i][c?1]+f[c][j]+s[j]?s[i?1])
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int n,x,j,s[101],f[101][101]; int main() {memset(f,127/3,sizeof(f));scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d",&x);s[i]=s[i-1]+x;//前綴和f[i][i]=0;}for (int k=2;k<=n;k++)//復(fù)制長(zhǎng)度for (int i=1;i<=n-k+1;i++){j=i+k-1;//求出后面的數(shù)for (int c=i+1;c<=j;c++)f[i][j]=min(f[i][j],f[i][c-1]+f[c][j]+s[j]-s[i-1]);}printf("%d",f[1][n]); }方法三方法三方法三
方法與前面的一樣,但是f[i][j]表示的是從第i個(gè)開始后面的j個(gè)數(shù),導(dǎo)致了寫法不同
動(dòng)態(tài)轉(zhuǎn)移方程
f[i][j]=min(f[i][j],f[i][c]+f[i+c][j?c]+s[i+j?1]?s[i?1])f[i][j]=min(f[i][j],f[i][c]+f[i+c][j-c]+s[i+j-1]-s[i-1])f[i][j]=min(f[i][j],f[i][c]+f[i+c][j?c]+s[i+j?1]?s[i?1])
i+c是第二段的開頭,j-c是的二段的長(zhǎng)度
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; int n,x,s[101],f[101][101]; int main() {memset(f,127/3,sizeof(f));scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%d",&x);s[i]=s[i-1]+x;//前綴和f[i][1]=0;}for (int j=2;j<=n;j++)//枚舉長(zhǎng)度,但表達(dá)不一樣for (int i=1;i<=n-j+1;i++)//枚舉前面的數(shù)for (int c=1;c<j;c++)//枚舉分割線f[i][j]=min(f[i][j],f[i][c]+f[i+c][j-c]+s[i+j-1]-s[i-1]);printf("%d",f[1][n]); } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的【动态规划】石子合并 (ssl 2863)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Stellantis 集团将投资 15
- 下一篇: 【动态规划】机器分配 (ssl 1639