POJ 1738:An old Stone Game 石子归并 (GarsiaWachs算法)

There is an old stone game.At the beginning of the game the player picks n(1<=n<=50000) piles of stones in a line. The goal is to merge the stones in one pile observing the following rules: 
At each step of the game,the player can merge two adjoining piles to a new pile.The score is the number of stones in the new pile. 
You are to write a program to determine the minimum of the total score.

Input

The input contains several test cases. The first line of each test case contains an integer n, denoting the number of piles. The following n integers describe the number of stones in each pile at the beginning of the game. 
The last test case is followed by one zero.

Output

For each test case output the answer on a single line.You may assume the answer will not exceed 1000000000.

Sample Input

1
100
3
3 4 3
4
1 1 1 1
0

Sample Output

0
17
8
 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define MAX 55555
 6 using namespace std;
 7 int a[MAX],n,num,result;
 8 void combine(int k)
 9 {
10     int i,j;
11     int temp=a[k]+a[k-1];
12     result+=temp;
13     for(i=k;i<num-1;i++)
14         a[i]=a[i+1];
15     num--;
16     for(j=k-1;j>0&&a[j-1]<temp;j--)
17         a[j]=a[j-1];
18     a[j]=temp;
19     while(j>=2&&a[j]>=a[j-2])
20     {
21         int d=num-j;
22         combine(j-1);
23         j=num-d;
24     }
25 }
26 int main()
27 {
28     int i;
29     while(scanf("%d",&n)&&n){
30         if(n==0) return 0;
31         for(i=0;i<n;i++)
32             scanf("%d",&a[i]);
33         num=1;
34         result=0;
35         for(i=1;i<n;i++){
36             a[num++]=a[i];
37             while(num>=3&&a[num-3]<=a[num-1])
38                 combine(num-2);
39         }
40         while(num>1) combine(num-1);
41         printf("%d\n",result);
42     }
43     return 0;
44 }
时间: 2024-10-12 09:12:35

POJ 1738:An old Stone Game 石子归并 (GarsiaWachs算法)的相关文章

POJ 1738 An old Stone Game(石子合并 经典)

An old Stone Game Time Limit: 5000MS   Memory Limit: 30000K Total Submissions: 3672   Accepted: 1035 Description There is an old stone game.At the beginning of the game the player picks n(1<=n<=50000) piles of stones in a line. The goal is to merge

合并类动态规划,石子归并,合并石子解题报告

石子归并问题 1:任意版 有N堆石子,现要将石子有序的合并成一堆,规定如下:每次只能移动任意的2堆石子合并,合并花费为将的一堆石子的数量.设计一个算法,将这N堆石子合并成一堆的总花费最小(或最大). 此类问题比较简单,就是哈夫曼编码的变形,用贪心算法即可求得最优解.即每次选两堆最少的,合并成新的一堆,直到只剩一堆为止.证明过程可以参考哈夫曼的证明过程. 2.链式归并 问题描述 设有N堆沙子排成一排,其编号为1,2,3,-,N(N<=100).每堆沙子有一定的数量.现要将N堆沙子并成为一堆.归并的

石子归并-2:区间DP{环形}

题目描述 Description 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入描述 Input Description 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数. 输出描述 Output Description 输出共2行,第1行为最小得分,第2行为最大得分. 样例输入

动态规划中的石子归并问题

一.有N堆石子,每堆的重量是w[i],可以任意选两堆合并,每次合并的花费为w[i]+w[j],问把所有石子合并成为一堆后的最小花费是多少.因为是可以任意合并,所以每次合并的时候选最小的两堆合并,贪心即可. 二.有N堆石子,每堆的重量是a[i],排成一条直线,每次只能合并相邻的两堆,直到合成一堆为止,问最后的最小花费是多少.分析:因为规定了只能合并相邻的两堆,显然不能使用贪心法.分成子问题来考虑,定义dp[i][j]表示从第i的石子合并到第j个石子的最小花费,那么dp[1][N]就是问题的解.可以

POJ 1740 A New Stone Game(博弈)题解

题意:有n个石子堆,每一个都可以轮流做如下操作:选一个石堆,移除至少1个石子,然后可以把这堆石子随便拿几次,随便放到任意的其他石子数不为0的石子堆,也可以不拿.不能操作败. 思路:我们先来证明,如果某个石子数有偶数堆,则先手必败,因为无论先手怎么做,后手都能模仿先手,最后把石子取光.显然全是偶数堆是必败态.如果有奇数堆怎么办?我们就把最大的奇数堆取光,然后把其他奇数堆变成偶数堆.但是一定能保证可以吗?答案是可以.假设奇数堆的石子数为 x1,x2,x3...xn,那么我们分别给每一堆加上x2-x1

3002 石子归并 3

时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=3000) 第二行n个整数w1,w2...wn  (wi <= 3000) 输出描述 Outpu

1048 石子归并

1048 石子归并 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子,一次合并的代价为两堆石子的重量和w[i]+w[i+1].问安排怎样的合并顺序,能够使得总合并代价达到最小. 输入描述 Input Description 第一行一个整数n(n<=100) 第二行n个整数w1,w2...wn  (wi <= 100) 输出描述 Output Des

石子归并(dp)

石子归并 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 89  Solved: 22 [Submit][Status][Web Board] Description 现在有n堆石子,第i堆有ai个石子.现在要把这些石子合并成一堆,每次只能合并相邻两个,每次合并的代价是两堆石子的总石子数.求合并所有石子的最小代价. Input 第一行包含一个整数T(T<=50),表示数据组数. 每组数据第一行包含一个整数n(2<=n<=100),表示石子的

AC日记——石子归并 51nod 1021

石子归并 思路: 经典动态规划——归并类问题: 我们把状态划为n个,即1-n的n个长度为n个状态: 那么,每个长度为i的状态都可以由i-1个长度为i-1的状态推出: 所以,dp转移方程: dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); 来,上代码: #include <cstdio> #include <cstring> #include <iostream> #include <algori