石子合併問題(環形)

石子合併問題

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章