石子合併問題
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
在一個圓形操場的四周擺放着n堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2 堆石子合併成新的一堆,並將新的一堆石子數記爲該次合併的得分。試設計一個算法,計算出將n堆石子合併成一堆的最小得分和最大得分。
對於給定n堆石子,計算合併成一堆的最小得分和最大得分。
Input
輸入數據的第1行是正整數n,1≤n≤100,表示有n堆石子。第二行有n個數,分別表示每堆石子的個數。
Output
輸出數據有兩行,第1行中的數是最小得分,第2行中的數是最大得分。
Sample Input
4
4 4 5 9
Sample Output
43
54
#include <bits/stdc++.h>
using namespace std;
int arr[205];
int dp_1[205][205],dp_2[205][205];
int sum[205];
int main()
{
int n,ans_min = 2e9,ans_max = -1,j;
sum[0] = 0;
cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>arr[i];
sum[i] = sum[i-1] + arr[i];
}
//通過取餘操作成環
for(int i = n+1; i <= 2*n; i++)
{
sum[i] = sum[i-1] + arr[i%n];
}
memset(dp_1,0,sizeof(dp_1));
memset(dp_2,0,sizeof(dp_2));
for(int m = 1; m < n; m++)
{
for(int i = 1; i < 2*n; i++)
{
j = i + m;
if(j >= 2*n)
break;
dp_2[i][j] = 2e9;
for(int k = i; k < j; k++)
{
dp_1[i][j] = max(dp_1[i][j],dp_1[i][k]+dp_1[k+1][j] + sum[j]-sum[i-1]);
dp_2[i][j] = min(dp_2[i][j],dp_2[i][k]+dp_2[k+1][j] + sum[j]-sum[i-1]);
}
}
}
for(int i = 1; i < 2*n; i++)
{
j = i + n-1;
if(j >= 2*n) break;
ans_max = max(ans_max,dp_1[i][j]);
ans_min = min(ans_min,dp_2[i][j]);
}
cout<<ans_min<<endl;
cout<<ans_max<<endl;
return 0;
}