Stone merger (the ring)

You see me you Da Buda
This link: https://blog.csdn.net/KO812605128/article/details/101196345

Stone merger
Time Limit: 1000 ms Memory Limit: 65536 KiB

Problem Description
In a circular four weeks playground placed stones piled n. Stone is to have the order to merge into a pile. Provisions can only choose two adjacent pile into a new pile of stones, a pile of stones and a few new record for the combined score. Try to design an algorithm to calculate the n combined into a pile of stones piled minimum score and maximum score.
For a given n gravel pile, merge into a pile calculating the minimum and maximum score score.
Input
line of the first input data is a positive integer n, 1≤n≤100, n represents stones piled there. The second row has a number of n, respectively, represent the number of each pile of stones.
Output
Output data of two lines, the first line number is the minimum score, the second number of rows is the maximum score.
The Input the Sample
. 4
. 4. 5. 4. 9
the Sample the Output
43 is
54 is
Continued Example describes the analysis of
the minimum value:

4 4 5 9 score: 0
8 5 9 score: 8
13 9 score: 8 + 13 = 21
22 score: 8 + 13 + 22 = 43

Maximum:

4 4 5 9 score: 0
4 4 14 score: 14
4 18 score: 4 + 18 = 22
22 score: 14 + 18 + 22 = 54

Reference original blog : explain a good

analysis

Suppose stones Ai, Ai + 1, ......, Ai + j-1 j stack were to be merged, simply referred to as A [i + 0, i + j-1]. If the last set in a merger with Ak + Ak between 1 (i <= k <= i + j-1), then the combined score of the last
Ai, Ai + 1, ......, Ai + j-1 number stack sum referred to as stones totalValue (i , j). (regardless of the last time you merge occurred at which position, totalValue (i, j) values are the same) so the total score is equal to

. A [i, k] + A [k + 1, i + j-1] + totalValue (i, j)
Here Insert Picture Description
dynamic programming ideas:

阶段i:石子的每一次合并过程,先两两合并,再三三合并,…最后N堆合并 
状态s:每一阶段中各个不同合并方法的石子合并总得分。 
决策:把当前阶段的合并方法细分成前一阶段已计算出的方法,选择其中的最优方案 
具体来说我们应该定义一个数组s[i,j]用来表示合并方法,s[i][j]表示从第i堆开始数j堆进行合并,s[i,j]为合并的最优得分。
 对例子(3 4 6 5 4 2)来说:
 第一阶段:s[1,1]=0,s[2,1]=0,s[3,1]=0,s[4,1]=0,s[5,1]=0,s[6,1]=0,因为一开始还没有合并,所以这些值应该全部为0
 第二阶段:两两合并过程如下,其中sum(i,j)表示从i开始数j个数的和
           s[1,2]=s[1,1]+s[2,1]+sum(1,2)
           s[2,2]=s[2,1]+s[3,1]+sum(2,2)
           s[3,2]=s[3,1]+s[4,1]+sum(3,2)
           s[4,2]=s[4,1]+s[5,1]+sum(4,2)
           s[5,2]=s[5,1]+s[6,1]+sum(5,2)
           s[6,2]=s[6,1]+s[1,1]+sum(6,2)
 第三阶段:三三合并可以拆成两两合并,拆分方法有两种,前两个为一组或后两个为一组
      s[1,3]=s[1,2]+s[3,1]+sum(1,3)或s[1,3]=s[1,1]+s[2,2]+sum(1,3),取其最优(最大或最小)
      s[2,3]=s[2,2]+s[4,1]+sum(2,3)或s[1,3]=s[2,1]+s[3,2]+sum(2,3),取其最优                                                                      
 第四阶段:四四合并的拆分方法用三种,同理求出三种分法的得分,取其最优即可。以后第五阶段、第六阶段依次类推,
 最后在第六阶段中找出最优答案即可。

AC Code:


#include<bits/stdc++.h>

using namespace std;

const int Max = 99999;
const int Min = 0;

int n, a[200];///n表示堆数,a表示每队的数量
int dp[200][200];///dp[i][j]表示从第i堆开始合并j堆(包括第i堆)后的最小花费
int dq[200][200];///dq表示最大

int sum(int i, int t)///从第i堆开始,t个石堆合,最后一次的合并的花费
{
    int s = 0, k1, k;
    for(k = i; k < i + t; k++)
    {
        k1 = k % n;
        if(k1 == 0) k1 = n;
        s = s + a[k1];///这t个石堆最好两堆合并时的花费一定是这t堆石子的总和
    }
    return s;
}

int main()
{
    cin>>n;
    for(int i = 1; i <= n; i++)
    {
        cin>>a[i];
        dp[i][1] = 0;///表示合并一堆的花费,没有合并则花费为0
        dq[i][1] = 0;
    }
    ///动态规划
    for(int t = 2; t <= n; t++)
    {
        for(int i = 1; i <= n; i++)
        {
            dp[i][t] = Max;
            dq[i][t] = Min;
            for(int k = 1; k < t; k++)
            {
                dp[i][t] = min(dp[i][t], dp[i][k] + dp[(i + k - 1) % n + 1][t - k] + sum(i, t));
                dq[i][t] = max(dq[i][t], dq[i][k] + dq[(i + k - 1) % n + 1][t - k] + sum(i, t));
            }
        }
    }
    int mmin = Max;
    int mmax = Min;
    for(int i = 1; i <= n; i++)///从第几堆石子开始结果最小
    {
        mmin = min(mmin, dp[i][n]);
        mmax = max(mmax, dq[i][n]);
    }
    cout<<mmin<<endl;
    cout<<mmax<<endl;
}

Test data codes, an aid to understanding, and prone to the wrong place

#include<bits/stdc++.h>

using namespace std;

const int Max = 99999;
const int Min = 0;

int n, a[200];///n表示堆数,a表示每队的数量
int dp[200][200];///dp[i][j]表示从第i堆开始合并j堆(包括第i堆)后的最小花费
int dq[200][200];///dq表示最大

int sum(int i, int t)///从第i堆开始,t个石堆合,最后一次的合并的花费
{
    int s = 0, k1, k;
    for(k = i; k < i + t; k++)
    {
        k1 = k % n;///作为数组的下标
        if(k1 == 0) k1 = n;
        s = s + a[k1];///这t个石堆最好两堆合并时的花费一定是这t堆石子的总和
    }
    return s;
}

int main()
{
    int i, k, j;
    cin>>n;
    for(i = 1; i <= n; i++)
    {
        cin>>a[i];
        dp[i][1] = 0;///表示合并一堆的花费,没有合并则花费为0
        //dq[i][1] = 0;
    }
    ///动态规划
    for(i = 2; i <= n; i++)
    {
        for(j = 1; j <= n; j++)
        {
            dp[j][i] = Max;///求最大值把默认值初始化为最小值,反之
            //dq[j][i] = Min;
            for(k = 1; k < i; k++)
            {
                cout<<"dp["<<j<<"]["<<i<<"]="<<dp[j][i]<<"----"<<"dp["<<j<<"]["<<i<<"]="<<dp[j][k]<<"---(j+k-1)%n+1="<<(j + k - 1) % n + 1<<"---sum="<<sum(j, i)<<endl;
                dp[j][i] = min(dp[j][i], dp[j][k] + dp[(j + k - 1) % n + 1][i - k] + sum(j, i));
                //dq[j][i] = max(dq[j][i], dq[j][k] + dq[(j + k - 1) % n + 1][i - k] + sum(j, i));
                cout<<"dp["<<j<<"]["<<i<<"]="<<dp[j][i]<<"---dp[j][k]+dp[(j+k-1)%n+1][i-k]+sum(j, i)="<<dp[j][k] + dp[(j + k - 1) % n + 1][i - k] + sum(j, i)<<endl;
                cout<<"KKKKK结束"<<endl;
                cout<<endl;
            }
            cout<<"JJJJJ结束"<<endl;
            cout<<endl;
        }
        cout<<"IIIII结束"<<endl;
        cout<<endl;
    }
    int mmin = Max;
    int mmax = Min;
    for(int i = 1; i <= n; i++)///从第几堆石子开始结果最小
    {
        mmin = min(mmin, dp[i][n]);
        //mmax = max(mmax, dq[i][n]);
    }
    cout<<mmin<<endl;
    //cout<<mmax<<endl;
}

This excerpt from a Han Han Fu Fu

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxx = 0x3f3f3f3f;

int main() 
{
	int n;
	cin >> n;
	int stone[210];
	int dp1[210][210];
	int dp2[210][210];
	int sum[210];
	int a1 = maxx;
	int a2 = 0;
	for (int i = 0; i <= 2 * n; i++)
	{
		for (int j = 0; j <= 2 * n; j++)
		{
			dp1[i][j] = maxx;
			dp2[i][j] = -1;
		}
	}
	for (int i = 1; i <= n; i++)
	{
		cin >> stone[i];
		stone[i + n] = stone[i];
		dp1[i][i] = dp2[i][i] = dp1[i + n][i + n] = dp2[i + n][i + n] = 0;
	}
	sum[0] = 0;
	for (int i = 1; i <= 2 * n - 1; i++)
	{
		sum[i] = stone[i] + sum[i - 1];
	}
	for (int len = 1; len <= n - 1; len++)
	{
		for (int i = 1; i <= 2 * n - 1; i++)
		{
			int j = i + len;
			if (j >= (2 * n)) break;
			int k;
			if (len == 1) dp1[i][j] = dp2[i][j] = sum[j] - sum[i-1];
			else
			{
				for (k = i; k < j; k++)
				{
					dp1[i][j] = min(dp1[i][j], dp1[i][k] + dp1[k + 1][j] + sum[j] - sum[i - 1]);
					dp2[i][j] = max(dp2[i][j], dp2[i][k] + dp2[k + 1][j] + sum[j] - sum[i - 1]);
				}
			}
			
		}
	}
	for (int i = 1; i <= n; i++)
	{
		a1 = min(a1, dp1[i][i + n - 1]);
		a2 = max(a2, dp2[i][i + n - 1]);
	}
	cout << a1 << "\n" << a2 << "\n";
	return 0;
}

Guess you like

Origin blog.csdn.net/KO812605128/article/details/101196345