最近由于省级比赛将近,更新频率从明天(7月1日)起改为每日一更(或两更),与常州市赛/江苏省赛有关内容也会减少。谢谢大家的支持!
原题链接:https://www.luogu.com.cn/problem/P1223排队接水 - 洛谷排队接水 - 洛谷https://www.luogu.com.cn/problem/P1223排队接水 - 洛谷
题目描述
有n个人在一个水龙头前排队接水,假如每个人接水的时间为T_iTi请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小。
输入
第一行为一个整数n。
第二行n个整数,第i个整数Ti表示第i个人的等待时间Ti。
输出
输出文件共两行,第一行为一种平均时间最短的排队顺序。
第二行为这种排列方案下的平均等待时间(输出结果精确到小数点后两位)。
样例组
输入
10
56 12 1 99 1000 234 33 55 99 812
输出
3 2 7 8 1 4 9 6 10 5
291.90
说明/提示
n≤1000,ti ≤10^6n≤1000,ti≤106,不保证ti不重复。
当ti重复时,按照输入顺序即可(sort 是可以的)。
解题思路
根据题目提示(sort 是可以的),我们可以知道这是一道简单排序性贪心。那简单排序性贪心的题目主程序就一句话:
sort(a+1,a+n+1);//a是目标数组
所以这道题目的难点还是统计与计数部分。
这道题目也可以被定义为基于冒泡的贪心。基于冒泡的贪心就是在冒泡排序中途进行一系列操作,那主要就是冒泡排序的程序。基于冒泡的贪心主程序如下:
//源程序见https://blog.csdn.net/ceshyong/article/details/125460633?spm=1001.2014.3001.5502
void bubble_sort(int n,int &a[],int &b[])
{
for(int i=1;i<=n;i++) b[i]=i;
for(int i=1;i<=n;i++)
{
bool f=0;
for(int j=1;j<n;j++)
{
if(a[j]>a[j+1])
{
swap(b[j],b[j+1]);
swap(a[j],a[j+1]);
f=1;
}
}
if(f==0) return;
}
}
而由于统计与计数方式不同,基于简单排序性贪心也有两种方法。
第一种办法是双循环(类似快排sort)+三数组。这种方法比较麻烦,但也是最基础的一种方法。用这种办法写的程序如下:
void cx(int n,int &a[],int &b[],int &u)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i]==b[j])
{
if(u[j]==0)
{
u[j]=1;
cout<<j<<' ';
}
}
}
}
}
第三种方法是借助STL库里的pair<>。用STL库写这样定义:
vector<pair<int,int> >a;
输入的方法如下:
void dr(int n)
{
int m;
for(int i=1;i<=n;i++)
{
cin>>m;
a.push_back(make_pair(m,i));
}
}
然后直接sort(a.begin(),a.end())就行了。
代码
具体代码如下:
基于简单排序性贪心代码:
#include<bits/stdc++.h>
#define maxn 10002
using namespace std;
int a[maxn],b[maxn],n,res;
void bubble_sort()
{
for(int i=1;i<=n;i++) b[i]=i;
for(int i=1;i<=n;i++)
{
bool f=0;
for(int j=1;j<n;j++)
{
if(a[j]>a[j+1])
{
swap(b[j],b[j+1]);
swap(a[j],a[j+1]);
f=1;
}
}
if(f==0) return;
}
}
int main()
{
double t=0;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
bubble_sort();
for(int i=1;i<=n;i++) cout<<b[i]<<' ',t+=a[i]*(n-i);
cout<<endl<<fixed<<setprecision(2)<<t/n;
return 0;
}
有图为证。
基于冒泡的贪心代码:
#include<bits/stdc++.h>
using namespace std;
int a[100001],u[100001],b[100001],n;
int main()
{
double time=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i]==b[j])
{
if(u[j]==0)
{
u[j]=1;
cout<<j<<' ';
}
}
}
}
for(int i=1;i<=n;i++) time+=a[i]*(n-i);
cout<<endl<<fixed<<setprecision(2)<<1.0*time/n;
return 0;
}
有图为证(梅开二度) :
基于STL的代码:
#include<bits/stdc++.h>
using namespace std;
vector<pair<int,int> >a;int n,m,res;double t=0;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>m;
a.push_back(make_pair(m,i));
}
sort(a.begin(),a.end());
for(int i=0;i<n;i++) cout<<a[i].second<<' ';
for(int i=1;i<n;i++) res+=a[i-1].first,t+=res;
cout<<endl<<fixed<<setprecision(2)<<t/n;
return 0;
}
有图为证(三羊开泰):
这道题目就这么多(花了我两个多小时,写死我了)。