最小交换合并
Time Limit:1000MS Memory Limit:65536K
Description
在操场上沿一直线排列着 n堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的两堆石子合并成新的一堆, 并将新的一堆石子数记为该次合并的得分。允许在第一次合并前对调一次相邻两堆石子的次序。
计算在上述条件下将n堆石子合并成一堆的最小得分和初次交换的位置。
Input
输入数据共有二行,其中,第1行是石子堆数n≤100;
第2行是顺序排列的各堆石子数(≤20),每两个数之间用空格分隔。
Output
输出合并的最小得分。
Sample Input
3
2 5 1
Sample Output
11
#include <stdio.h> #define inf 2100000000 int sum[101], fmin[101][101], a[101]; int min(int a, int b) { if(a<b) return a; return b; } int max(int a, int b) { if(a>b) return a; return b; } int main() { int n, i, j, k, ceng, ans=inf; scanf("%d", &n); for(i=1; i<=n; i++) { scanf("%d", &a[i]); sum[i]=a[i]+sum[i-1]; } for(ceng=1; ceng<n; ceng++) { sum[ceng]+=a[ceng+1]-a[ceng]; for(i=1; i<=n; i++) for(j=1; j<=n; j++) fmin[i][j]=inf; for(i=1; i<=n; i++) fmin[i][1]=0; for(j=2; j<=n; j++) for(i=1; i<=n-j+1; i++) for(k=1; k<=j-1; k++) fmin[i][j]=min(fmin[i][j], sum[i+j-1]-sum[i-1]+fmin[i][k]+fmin[i+k][j-k]); ans=min(fmin[1][n], ans); sum[ceng]+=a[ceng]-a[ceng+1]; } printf("%d", ans); return 0; }