石子合并问题

戏子无情 提交于 2019-11-25 16:53:39

石子合并问题
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
Hint

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int max1 = 101;
const int INF = 0x3f3f3f3f;
int a[max1],maxn[max1][max1],minn[max1][max1];///minn[i][j]表示从i堆合并成j堆的最小费用。
int n;
int getsum(int i,int len) ///从i堆到len堆的和
{
    int sum = 0;
    for(; len > 0; i++,len--)
        sum+=a[(i-1)%n + 1];
    return sum;
}
int main()
{
memset(minn,INF,sizeof(minn));
scanf("%d",&n);
for(int i = 1; i <= n; i++)
{
    scanf("%d",&a[i]);
    minn[i][1] = 0;  ///边界
}
///递推方程
for(int len = 2; len <= n; len++)
{
    for(int i =1; i <= n; i++)
    {
        for(int k = 1; k <len; k++)
        {
            minn[i][len] = min(minn[i][len],minn[i][k]+minn[(i+k-1)%n+1][len - k]+getsum(i,len));
            maxn[i][len] = max(maxn[i][len],maxn[i][k]+maxn[(i+k-1)%n+1][len - k]+getsum(i,len));
        }
    }
}
int sum1 = INF,sum2 = 0;
for(int i = 1; i <= n; i++)  ///遍历所有情况得出从第i堆开始合并可以得到的最值
{
    sum1 = min(sum1,minn[i][n]);
    sum2 = max(sum2,maxn[i][n]);
}
printf("%d\n%d",sum1,sum2);
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!