您的位置:首页 > 其它

石子合并问题(直线版)

2015-05-11 01:10 281 查看
首先来个题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=737

有个更难的版本(不过很好玩):http://www.lydsy.com/JudgeOnline/problem.php?id=3229

题目:

石子合并(一)

时间限制:1000 ms | 内存限制:65535 KB
难度:3

描述 有N堆石子排成一排,每堆石子有一定的数量。现要将N堆石子并成为一堆。合并的过程只能每次将相邻的两堆石子堆成一堆,每次合并花费的代价为这两堆石子的和,经过N-1次合并后成为一堆。求出总的代价最小值。

输入有多组测试数据,输入到文件结束。
每组测试数据第一行有一个整数n,表示有n堆石子。
接下来的一行有n(0< n <200)个数,分别表示这n堆石子的数目,用空格隔开输出输出总代价的最小值,占单独的一行样例输入
3
1 2 3
7
13 7 8 16 21 4 18

样例输出
9
239


最普通的算法O(n^3):

#include <fstream>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
using namespace std;

const int N = 205;
const int INF = 0x7fffffff;

int stone
;
int n,t,ans;

void combine(int k)
{
int tmp = stone[k] + stone[k-1];
ans += tmp;
for(int i=k;i<t-1;i++)
stone[i] = stone[i+1];
t--;
int j = 0;
for(j=k-1;stone[j-1] < tmp;j--)
stone[j] = stone[j-1];
stone[j] = tmp;
while(j >= 2 && stone[j] >= stone[j-2])
{
int d = t - j;
combine(j-1);
j = t - d;
}
}

int main()
{
//freopen("D:\\input.in","r",stdin);
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d",stone+i);
stone[0]=INF;
stone[n+1]=INF-1;
t = 3;
ans = 0;
for(int i=3;i<=n+1;i++)
{
stone[t++] = stone[i];
while(stone[t-3] <= stone[t-1])
combine(t-2);
}
while(t > 3) combine(t-1);
printf("%d\n",ans);
}
return 0;
}


0ms
小细节在于把数列前后加两个值INF和INF-1。这样就不需要每次判别上下界。至于-1,组合堆的最后一步里体现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: