Loading
NOIP2006普及組 明明的隨機數
NOIP2001提高組 一元三次方程求解

NOIP2004提高組 合併果子

Freddy posted @ 2011年10月08日 03:26 in NOIP with tags noip 貪心 c++ , 1451 阅读

【问题描述】
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过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

恭喜你通过了全部测试点!

 

Finance Essay Help U 说:
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.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter