https://www.51nod.com/contest/Problem.html#!problemId=2133&contestId=54
排队接水
基准时间限制:1 秒 空间限制:131072 KB 分值: 5
n个人一起排队接水,第i个人需要b[i]的时间来接水。
1 <= n <= 1000
0 <= b[i] <= 1000
同时只能有一个人接水,正在接水的人和没有接水的人都需要等待。
完成接水的人会立刻消失,不会继续等待。
你可以决定所有人接水的顺序,并希望最小化所有人等待时间的总和。
Input
第一行一个整数n
接下来n行,每行一个整数表示b[i]
Output
一行一个整数,表示所有人等待时间的总和的最小值
Input示例
3
1
2
3
Output示例
10
思路1(贪心算法)
倒数第i个人,对总时间造成的贡献是:i*b; 因为他自己要等b[i],其他n-i-1个人也要等b[i]
为使得总时间越小,应当把b大的放在后面;把b小的放在前面;
所以要对数组b进行排序;
#include <iostream>
#include <cstdio>
#include<algorithm>
using namespace std;
int a[1010];
int main(int argc, char** argv) {
int n;
int sum=0;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);//从小到大排序
for(int i=0;i<n;i++){
sum+=(n-i)*a[i];//倒数第n个人,对时间的贡献
} //(自己要等a[i],其他n-i-1个人也要等a[i]
cout<<sum<<endl;
}
return 0;
}
思路2(贪心算法+考虑相邻两个人)
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
bool cmp(const int &a,const int &b){//比较相邻两个人
return 2*a+b<2*b+a;
} //a在前,两人需要总时间:a+(a+b)
//b在前,两任需要总时间: b+(b+a)
int main(int argc, char** argv) {
int a[1001];
int n;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n,cmp);
int sum=0;
for(int i=0;i<n;i++){
sum+=(n-i)*a[i];
}
cout<<sum<<endl;
}
return 0;
}
思路2(优先队列)
#include <iostream>
#include <queue>
#include <cstdio>
using namespace std;
int main(int argc, char** argv) {
priority_queue<int,vector<int>,greater<int>>q;//greater是小根堆,从小到大输出
//priority_queue<int,vector<int>,less<int>>q; // less是大根堆, 从大到小输出
//priority_queue<int>q默认从大到小排序(大根堆)
int n;
int x;
while(cin>>n){
for(int i=0;i<n;i++){
cin>>x;
q.push(x);
}
int sum=0;
while(!q.empty()){
//while(q.size()){
sum+=q.top()*q.size();//a[i]*(n-i)
q.pop();
}
cout<<sum<<endl;
}
return 0;
}