题目:
题目描述
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过 n−1n−1 次合并之后, 就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为 11 ,并且已知果子的种类 数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
例如有 33 种果子,数目依次为 11 , 22 , 99 。可以先将 11 、 22 堆合并,新堆数目为 33 ,耗费体力为 33 。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为 1212 ,耗费体力为 1212 。所以多多总共耗费体力 =3+12=15=3+12=15 。可以证明 1515 为最小的体力耗费值。
输入格式
共两行。
第一行是一个整数 n(1≤n≤10000)n(1≤n≤10000) ,表示果子的种类数。
第二行包含 nn 个整数,用空格分隔,第 ii 个整数 ai(1≤ai≤20000)ai(1≤ai≤20000) 是第 ii 种果子的数目。
输出格式
一个整数,也就是最小的体力耗费值。输入数据保证这个值小于 231231 。
输入输出样例
输入 #1
3 1 2 9
输出 #1
15
说明/提示
对于 30%30% 的数据,保证有 n≤1000n≤1000:
对于 50%50% 的数据,保证有 n≤5000n≤5000;
对于全部的数据,保证有 n≤10000n≤10000。
我是一名小学生,接触C++一年左右;
当我看到这一题,和大部分初学者一样;
初始思路:
1、定义数组
2.排序
3.按照题目模拟
下面附上代码:
#include <bits/stdc++.h>//万能头文件
#include <iostream>//无聊多打几个头文件
#include <cmath>//无聊多打几个头文件
#include <cstring>//无聊多打几个头文件
using namespace std;
long long arrway[10000000];//果子数组
int main()//代码开始
{
long long n;//有n个苹果
cin>>n;//输入
for(int i=1;i<=n;++i) cin>>arrway[i];//循环读入苹果
//sort(arrway.begin(),arrway.end());//从小到大排序
long long ans=0;//定义计数器
for(int i=1;i<n;++i)//有n-1次合并
{
arrway[i+1]=arrway[i]+arrway[i+1];
ans+=arrway[i+1];
}
cout<<ans;
return 0;//愉快的结束了
}
可是:
只对第一个点!!!
于是我开始思考对策,我在想是不是模拟要用到高精度,于是我写了一篇带高精度的
代码:
#include <bits/stdc++.h>//万能头文件
#include <iostream>//无聊多打几个头文件
#include <cmath>//无聊多打几个头文件
#include <cstring>//无聊多打几个头文件
using namespace std;
long long arrway[10000000];//果子数组
int a[1000],b[1000],c[1000];
string jia(string s1,string s2)
{
for(int i=0;i<int(s1.size());++i)
a[s1.size()-i-1]=s1[i]-'0';
for(int i=0;i<int(s2.size());++i)
b[s2.size()-i-1]=s2[i]-'0';
int len=max(s1.size(),s2.size());
for(int i=0;i<len;++i){
c[i]=a[i]+b[i];
}
for(int i=0;i<len;++i)
{
if(c[i]>=10){
c[i+1]++;
c[i]%=10;
}
}
if(c[len]!=0) len++;
string r;
for(int i=len-1;i>=0;--i) r+=char(c[i]+'0');
return r;
}
int main()//代码开始
{
long long n;
string ans;
cin>>n;
for(int i=1;i<=n;++i) cin>>arrway[i];
sort(a+0,a+n);
string str;
for(int i=1;i<n;++i)
{
str=jia(to_string(arrway[i]),to_string(arrway[i+1]));
ans=jia(ans,str);
}
cout<<ans;
return 0;//愉快的结束了
}
结果.........
一点改变都没有
不死心的我继续思考错误,于是我把注意力放在了排序上,这是我想到了复杂度最低的桶排序;
代码:
#include <bits/stdc++.h>
using namespace std;
const int MAXN=20000+5;
int a[MAXN],n,x,ans,idx,sum;//sum代表当前的数量,ans代表总共的数量
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>x;
a[x]++;
}
for(int i=0;i<=20004;++i){
if(a[i]!=0&&idx!=2){
idx++;
sum+=i;
a[sum]++;
}
if(idx==2){
idx=0;
ans+=sum;
sum=0;
}
}
cout<<ans;
return 0;
}
呵呵呵
不WA了但RE了..........................
这是我想到了堆排序,于是我开了一个小跟堆
代码:::
#include <bits/stdc++.h>
using namespace std;
int n,x,sum = 0,ans = 0;
priority_queue<int,vector<int>,greater<int> > q;//小根堆
int main(){
cin>>n;
for(int i=1;i<=n;++i){
cin>>x;
q.push(x);
}
while(q.size()>1){
int frist = q.top();
sum+=frist;
q.pop();
int sancan = q.top();
q.pop();
sum+=sancan;
ans+=sum;
q.push(sum);
sum = 0;
}
cout<<ans;
return 0;
}
终于!!!
AC了
思路
1.开一个小根堆
2.边读入编存
3.在堆里还有1个数的情况下
4.取出前两个数,合并;后重新放入堆
5.最后输出
好的今天题解结束了!!!
下期再见