1. 程式人生 > >Merge(石子合併加強版)

Merge(石子合併加強版)

好像是削弱版
雖說是三個合併,但是不是環形的,呵呵
60分,列舉兩個斷點,4層轉換
正解先合併兩堆,在列舉合併三堆的策略
即 3=1+1+1
3=2+1
but如果無法完全合併輸出最大值,而最大值是1e9,不是maxint,我日

2、石子合併加強版(merge.pasccpp)
時間限制:1s;記憶體限制:256MB
【問題描述】
還記得經典題石子合併嗎?現在小 Y 將題目加強啦!
在一個圓形操場的四周擺放著 n 堆石子,現要將石子有次序地合併成一堆。規定每次
只能選取相鄰的三堆合併成新的一堆,並將新的一堆的石子數,記為該次合併的得分。
編一程式,讀入石子堆數 n 及每堆的石子數。選擇一種合併石子的方案,使得做(n-1
)/2 次合併,得分的總和最小; 【輸入檔案】 第 1 行一個數,表示石子堆數。 第 2 行是順序排列的各堆石子數(≤1000),每兩個數之間用空格分隔。 【輸出檔案】 輸出合併的最小得分。 【樣例輸入】 5 1 2 3 4 5 【樣例輸出】 21 【樣例解釋】 先合併(1 2 3),再合併(6 4 5) 【資料範圍】 對於 20%的資料,n=5 對於 60%的資料,n<=80 對於 100%的資料,n<=400
#include <queue>
#include <stack>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; int n,w[402],a[402],f1[402][402],f2[402][402]; int main() { freopen("merge.in","r",stdin); freopen("merge.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%d",&w[i]); a[i]=a[i-1]+w[i]; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
f1[i][j]=f2[i][j]=1000000000; //memset(f1,127/3,sizeof(f1));memset(f2,127/3,sizeof(f2)); for (int i=n;i;i--) { f1[i][i]=0; f1[i][i+2]=a[i+2]-a[i-1]; for (int j=i+3;j<=n;j++) { for (int k=i;k<j;k++) f2[i][j]=min(f2[i][j],f1[i][k]+f1[k+1][j]); for (int k=i;k<j;k++) f1[i][j]=min(f1[i][j],min(f1[i][k]+f2[k+1][j],f2[i][k]+f1[k+1][j])+a[j]-a[i-1]); } } printf("%d",f1[1][n]); return 0; }