排队接水
本题要注意,前面的人用时最短,等待时间就最短,所以需要将排队时间从小到大排序,再计算等待时间。
#include<bits/stdc++.h>
using namespace std;
struct node{
int id;
int time;
}nodes[1000001];
bool cmp(node a,node b){
return a.time<b.time;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>nodes[i].time;
nodes[i].id=i+1;
}
sort(nodes,nodes+n,cmp);
double sum=0;
for(int i=0;i<n-1;i++){
sum+=nodes[i].time*(n-i-1);
}
double num=n;
double ans=sum/num;
for(int i=0;i<n;i++){
cout<<nodes[i].id<<" ";
}
cout<<endl;
cout<<setiosflags(ios::fixed)<<setprecision(2)<<ans<<endl;
}
P1803 凌乱的yyy / 线段覆盖
用贪心的思想,结束时间越早,参加的比赛越多。因此将比赛时间用结束时间排序,如果上一个的结束时间小于等于下一个的开始时间,ans++
#include<bits/stdc++.h>
using namespace std;
struct node{
int start;
int ends;
}nodes[1000001];
bool cmp(node a,node b){
return a.ends<b.ends;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d%d",&nodes[i].start,&nodes[i].ends);
}
sort(nodes,nodes+n,cmp);
int ans=0,tmp=0;
for(int i=0;i<n;i++){
if(nodes[i].start>=tmp){
ans++;
tmp=nodes[i].ends;
}
}
cout<<ans<<endl;
}
P3817 小A的糖果
当两数之和大于x时,要优先选择后面的数,因为贪心算法,为了使后面的数相加更小
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
int main()
{
ll n,x,a,last=0,ans=0;
cin>>n>>x;
for(int i=0;i<n;i++){
cin>>a;
if(a+last>x){
ans+=(a+last-x);
last=x-last;
}
else
last=a;
}
cout<<ans<<endl;
return 0;
}
P1208 [USACO1.3]混合牛奶 Mixing Milk
这是个比较简单的贪心题,将m个数据以单价从小到大排序,因为单价越低,总费用越低
#include<bits/stdc++.h>
using namespace std;
struct node{
int p,a;
}nodes[5001];
bool cmp(node b,node c){
return b.p<c.p;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
cin>>nodes[i].p>>nodes[i].a;
sort(nodes,nodes+m,cmp);
int sum=0,ans=0;
for(int i=0;i<m;i++){
if(sum+nodes[i].a<n){
sum+=nodes[i].a;
ans+=nodes[i].p*nodes[i].a;
}
else{
int tmp=n-sum;
ans+=nodes[i].p*tmp;
break;
}
}
cout<<ans<<endl;
return 0;
}
P5019 [NOIP2018 提高组] 铺设道路
这题。。模拟的话,最后两个点会超时,害,先把超时的代码贴上(舍不得删掉yingyingying~)
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,mins=10005;
cin>>n;
int num[100001];
for(int i=0;i<n;i++){
cin>>num[i];
if(num[i]<mins)
mins=num[i];
}
if(mins!=0){
for(int i=0;i<n;i++)
num[i]-=mins;
}
int ans=mins;
int s=0,e=0;
while(1){
while(num[s]==0&&s<n)
s++;
if(s>=n){
break;
}
e=s;
while(e+1<n&&num[e+1]!=0)
e++;
for(int i=s;i<=e;i++)
num[i]--;
ans++;
}
cout<<ans<<endl;
}
然后用贪心法做,分两种情况:
① 当后一个深度大于前一个,需要加上两者的差
② 当后一个深度小于等于前一个,则ans不用变
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,ans=0;
cin>>n;
int num[100001];
for(int i=0;i<n;i++){
cin>>num[i];
if(i==0)
ans+=num[i];
else{
if(num[i]>num[i-1]){
ans+=(num[i]-num[i-1]);
}
}
}
cout<<ans<<endl;
}
P1094 [NOIP2007 普及组] 纪念品分组
本题要将价格从小到大排序,然后取两头的索引,能分组的尽量分组,分组越多,时间越短
#include<bits/stdc++.h>
using namespace std;
int main()
{
int w,n,ans=0;
cin>>w>>n;
int num[30001];
for(int i=0;i<n;i++)
cin>>num[i];
sort(num,num+n);
int l=0,r=n-1;
while(l<=r){
if(num[l]+num[r]<=w){
l++;
r--;
ans++;
}
else{
r--;
ans++;
}
}
cout<<ans<<endl;
}