NOIP2004提高組 合併果子
【问题描述】
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
【输入文件】
输入文件fruit.in包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。
【输出文件】
输出文件fruit.out包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于231。
【样例输入】
3
1 2 9
【样例输出】
15
【数据规模】
对于30%的数据,保证有n<=1000:
对于50%的数据,保证有n<=5000;
对于全部的数据,保证有n<=10000。
【分析】
貪心,每次找到最小的兩堆果子進行合併。
不要把本題看成石子歸併。
我用的是鏈表,全過了,但是速度較慢~
#include <fstream> using namespace std; ifstream fin("fruit.in"); ofstream fout("fruit.out"); class data { public: int key; //Other members HERE... int sen;//前驱 int next;//后继 }; data A[200000]; int top;//链表中元素的个数 void Insert(int key) { int point=0; while (key>A[point].key) { point=A[point].next; } //Create a new node A[top].key=key; A[top].next=point; A[top].sen=A[point].sen; A[point].sen=top;//后继的前驱等于自己 A[A[top].sen].next=top;//前驱的后继等于自己 top++; } void DeleteOne(int key) { int point=A[0].next; while(A[point].next!=-1) { if(A[point].key==key) { A[A[point].sen].next=A[point].next; //自己前驱的后继等于自己的后继 A[A[point].next].sen=A[point].sen; //自己后继的前驱等于自己的前驱 return; //跳出函数 } point=A[point].next; } } void print() { int point=A[0].next; while(A[point].next!=-1) { fout<<A[point].key<<endl; point=A[point].next; } } void debug() { for (int i=0;i<top;i++) fout<<i<<" "<<A[i].key<<" "<<A[i].sen<<" "<<A[i].next<<endl; } int GetMinElem() { int point=A[0].next; return A[point].key; } int main() { //Initialize A[0].key=-1;A[0].next=1;A[0].sen=-1; A[1].key=0Xfffffff;A[1].next=-1;A[0].sen=0; top=2; int num,key; fin>>num; for (int i=0;i<num;i++) { fin>>key; Insert(key);//插入一个关键字 } int liu=num; int cost=0; //debug(); while (liu!=1) { int m=GetMinElem(); DeleteOne(m); int n=GetMinElem(); DeleteOne(n); //fout<<m<<" "<<n<<endl<<endl; cost+=(m+n); Insert(m+n); liu--; } //print(); fout<<cost<<endl; return 0; }
正在连接评测机...
已连接到评测机
GRID | 1 |
名称 | Flitty |
系统版本 | 1.00 |
备注 | COGS 1号评测机 Flitty |
正在编译...
编译成功
测试点 | 结果 | 得分 | 运行时间 | 内存使用 | 退出代码 |
1 | 正确 | 10 | 0.000 s | 2614 KB | 0 |
2 | 正确 | 10 | 0.002 s | 2614 KB | 0 |
3 | 正确 | 10 | 0.002 s | 2614 KB | 0 |
4 | 正确 | 10 | 0.043 s | 2614 KB | 0 |
5 | 正确 | 10 | 0.096 s | 2614 KB | 0 |
6 | 正确 | 10 | 0.403 s | 2614 KB | 0 |
7 | 正确 | 10 | 0.503 s | 2614 KB | 0 |
8 | 正确 | 10 | 0.396 s | 2614 KB | 0 |
9 | 正确 | 10 | 0.500 s | 2614 KB | 0 |
10 | 正确 | 10 | 0.508 s | 2614 KB | 0 |
运行完成
运行时间 2.453 s
平均内存使用 2614 KB
测试点通过状况 AAAAAAAAAA
得分:100
恭喜你通过了全部测试点!
2018年12月14日 08:12
Incredible article! I am picking up from it. It's captivating and a marvellous substance. That is some extraordinary points of view with respect to this subject.