日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【动态规划】石子合并 (ssl 2863)

發(fā)布時(shí)間:2023/12/3 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【动态规划】石子合并 (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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。