总感觉今天的效率特别低,看了一天的课本和ppt,被几个例题弄的晕头转向的。好不容易临近傍晚把基础知识看完了一遍,还想着晚上可以刷一部分题目,可是没想到一个题我做了一晚上,直到现在,才算是稍微弄懂了点吧。(其实感觉这题困扰我的地方好像和贪心一点关系都没有QAQ)。
题目描述
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过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包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于2^31。
输入输出样例
说明
对于30%的数据,保证有n<=1000:
对于50%的数据,保证有n<=5000;
对于全部的数据,保证有n<=10000。
#include<bits/stdc++.h>
using namespace std;
int a[10001],sum=0;
void solve(int a[],int x,int y)
{
if(x==y)return ;
sort(a+x,a+y);
sum+=a[x]+a[x+1];
a[x+1]+=a[x];
solve(a,x+1,y);
}
int main()
{
int n;cin>>n;
for(int i=1;i<=n;++i)cin>>a[i];
solve(a,1,n);
cout<<sum;
return 0;
}
很明显,如果每次合并完都排序的话时间复杂度o(n*n*nlogn),n取10000,很容易就超时。之后改用了一个插入排序,时间复杂度明显
就降低了。
第二次提交代码:
#include<bits/stdc++.h>
using namespace std;
int a[10001],sum=0,n;
void solve(int a[],int x)
{
if(x==n)return ;
sum+=a[x]+a[x+1];
a[x+1]+=a[x];
if(a[x+1]>a[x+2]) //这里判断不能省
{
int t=a[x+1],i=x+2;
for(;a[i]<t&&i<=n;++i) //插入排序开始用while写,但感觉实现起来太复杂,用for关键注意当a[i]<t不成立时,i不会在++了,此时i的位置是不满足条件的第一个点。
{
a[i-1]=a[i];
}
a[i-1]=t;
}
solve(a,x+1);
}
int main()
{
/*freopen("3.text","r",stdin);
freopen("1.text","w",stdout);*/
cin>>n;
for(int i=1;i<=n;++i)cin>>a[i];
sort(a+1,a+1+n);
solve(a,1);
cout<<sum;
return 0;
}
这次虽然A了,不过还是想再用优先队列(自动排序)来做一遍。
之前对优先队列不太熟悉,所以今晚花了一晚上钻研它,真的钻了好久 重载 的牛角尖。
其实看了一晚上无非就这么几个知识点
:
//1、基本操作:
q.size();//返回q里元素个数
q.empty();//返回q是否为空,空则返回1,否则返回0
q.push(k);//在q的末尾插入k
q.pop();//删掉q的第一个元素
q.top();//返回q的第一个元素
q.back();//返回q的末尾元素
//2、常用定义形式:
priority_queue <int,vector<int>,less<int> > p;//从大到小排列
priority_queue <int,vector<int>,greater<int> > q;//从小到大排列
最后附上最后一次的代码(这样写真的好简单):
#include<bits/stdc++.h>
using namespace std;
priority_queue < int ,vector<int>,greater<int> > a;//这东西一定要记住,太好用了。
int main()
{
int n,m;cin>>n;
for(int i=1;i<=n;++i)
{
cin>>m;
a.push(m);
}
int sum=0,x,y;
for(int i=1;i<=n-1;++i)
{
x=a.top();a.pop();
y=a.top();a.pop();
sum+=x+y;
a.push(x+y);
}
cout<<sum;
return 0;
}
最后,今天还发现了一个.stable_sort(),比sort的稳定性要好,尤其在对结构体排序时。
明天将会是忙碌的一天。。。