1.P1090合并果子
题意:在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。
每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。
因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。
分析:从给出的个数里每次取两个最小的数相加,并将和放入数列;以下代码借助优先队列
AC代码:
#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> > q;//定义一个优先为小的优先队列
int main()
{
int n,x,a,b,ans=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x;
q.push(x);
}
for(int i=1;i<n;i++)
{
a=q.top();
q.pop();
b=q.top();
q.pop();
ans+=a+b;
q.push(a+b);
}
cout<<ans<<endl;
return 0;
}
##优先队列:
¢头文件: #include <queue>
定义:priority_queue<data_type> priority_queue_name; 如:priority_queue<int> q;//默认是大顶堆
操作:q.push(elem) 将元素elem置入优先队列 q.top() 返回优先队列的下一个元素
q.pop() 移除一个元素 q.size() 返回队列中元素的个数
q.empty() 返回优先队列是否为空
2.P1181 数列分段Section
#include<bits/stdc++.h>
using namespace std;
int a[100010];
int main()
{
int n,m,sum=0,ans=0;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
{
sum+=a[i];
if(sum+a[i+1]>m){ans++;sum=0;}
}
if(sum!=0)ans++;//注意若最后sum不为0,则ans要加一
cout<<ans<<endl;
return 0;
}
3.P1208混合牛奶
注:每天所有奶农的总产量大于Marry乳业的需求量。输入:n需要的牛奶总量,m提供牛奶的农民总数,m个农民分别的牛奶单价及牛奶量
分析:将单价升序排列,由最小单价开始买,注意数组的大小,太大太小都RE#include<bits/stdc++.h>
using namespace std;
struct milk{
int price;//牛奶单价
int num;//牛奶数量
int value;//花销
}a[5000010];
bool cmp(milk a,milk b)//单价由小到大排序
{
return a.price<b.price;
}
int main()
{
int n,m,money=0,sum=0;//n需要牛奶的总数 m农民数2
cin>>n>>m;
if(n==0||m==0){cout<<0<<endl;return 0;}
for(int i=1;i<=m;i++)
{
cin>>a[i].price>>a[i].num;
a[i].value=a[i].price*a[i].num;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
money+=a[i].value;
sum+=a[i].num;
if(sum==n){cout<<money<<endl;return 0;}
if(sum>n){sum-=a[i].num;money-=a[i].value;n-=sum;money+=n*a[i].price;cout<<money<<endl;return 0;}
}
}
4.P1223排队接水
分析:将时间升序排列
#include<bits/stdc++.h>
using namespace std;
struct water
{
double t;
int k;
}a[1010];
bool cmp(water c,water b)
{
return c.t<b.t;
}
int main()
{
int n;
double ans,sumt=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].t;
a[i].k=i;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
cout<<a[i].k<<' ';
if(i!=n){sumt+=a[i].t;ans+=sumt;}
}
ans=ans/n;
cout<<endl;
//printf("%0.2lf\n",ans);
cout<<fixed<<setprecision(2)<<ans<<endl;
return 0;
}
##cout的格式化输出
:
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
const int p=1.2345678,a=1234678;
cout<<hex<<a<<endl;//以十六进制形式输出
cout<<dec<<a<<endl;//以十进制形式输出
cout<<oct<<a<<endl;//以八进制形式输出
cout<<setw(5)<<p<<endl;//控制输出宽度为5,相当于printf("%5d",p);
cout<<setprecision(5)<<p<<endl;//控制输出有效数字的个数为5
cout<<fixed<<setprecision(5)<<p<<endl;//fixed表示控制小数点后面的数字,连用表示保留五位小数
cout<<hex<<uppercase<<a<<endl;//uppercase输出十六进制的大写字符
cout<<left<<setw(10)<<a<<endl;//控制结果左对齐输出
cout<<right<<setw(10)<<a<<endl;//控制结果右对齐输出
cout<<setfill('a')<<setw(10)<<a<<endl;//设置填充字符为a
return 0;
}
5,P1094纪念品分组
题意:元旦快到了,校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡,他要把购来的纪念品根据价格进行分组,但每组最多只能包括两件纪念品, 并且每组纪念品的价格之和不能超过一个给定的整数。为了保证在尽量短的时间内发完所有纪念品,乐乐希望分组的数目最少。你的任务是写一个程序,找出所有分组方案中分组数最少的一种,输出最少的分组数目。
输入:n纪念品之和上限,m纪念品总数,m个纪念品的价格 输出:最少分组数
分析:每组最多两件,排序后,取每次的最大值和最小值组合,若小于等于上限,则分为一组,若大于上限,则说明最大值只能自己一组。
AC代码:
#include<bits/stdc++.h>
using namespace std;
int a[3000010];
void qsort(int l,int r)//快排
{
int i,j,mid;
i=l;j=r;mid=a[(l+r)/2];
do
{
while(a[i]<mid)i++;
while(a[j]>mid)j--;
if(i<=j)
{
swap(a[i],a[j]);
i++;j--;
}
}while(i<=j);
if(l<j)qsort(l,j);
if(i<r)qsort(i,r);
}
int main()
{
int n,m,i,j,ans=0;
cin>>n>>m;
i=1,j=m;
for(int k=1;k<=m;k++)
cin>>a[k];
qsort(1,m);
while(i<=j)
{
if(a[i]+a[j]<=n){ans++;i++;j--;}//见分析
else{ans++;j--;}
}
cout<<ans<<endl;
return 0;
}
6.凌乱的YYY
题意:现在各大oj上有n个比赛,每个比赛的开始、结束的时间点是知道的。yyy认为,参加越多的比赛,noip就能考的越好(假的)所以,他想知道他最多能参加几个比赛。由于yyy是蒟蒻,如果要参加一个比赛必须善始善终,而且不能同时参加2个及以上的比赛。 输入:活动个数n 输出:n个活动的起始时间和结束时间
分析:将活动结束时间升序排序,判断每个结束时间是否与前一个起始时间重合
AC代码:
#include<iostream>
using namespace std;
int n,begin[1000010],end[1000010];
void init()//输入函数
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>begin[i]>>end[i];
}
void qsort(int x,int y)//快排
{
int i,j,mid,t;
i=x;j=y;mid=end[(x+y)/2];
while(i<=j)
{
while(end[i]<mid)i++;
while(end[j]>mid)j--;
if(i<=j)
{
swap(end[i],end[j]);
swap(begin[i],begin[j]);
i++;j--;
}
}
if(x<j)qsort(x,j);
if(i<y)qsort(i,y);
}
void solve()//处理
{
int ans=0,t=-1;
for(int i=1;i<=n;i++)
if(begin[i]>=t){ans++;t=end[i];}
cout<<ans<<endl;
}
int main()
{
init();
qsort(1,n);
solve();
return 0;
}
超时代码:
#include<bits/stdc++.h>
using namespace std;
struct time{ //定义时间结构体
int begin;
int end;
}a[1000010];
void qsort(int l,int r)//快排
{
int i,j,mid;
i=l;j=r;mid=a[(l+r)/2].end;
do{
while(a[i].end<mid)i++;
while(a[j].end>mid)j--;
if(i<=j)
{
swap(a[i].end,a[j].end);
i++;j--;
}
}while(i<=j);
while(l<j)qsort(l,j);
while(i<r)qsort(i,r);
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i].begin>>a[i].end;//输入起始时间和结束时间
qsort(1,n);//对结束时间进行升序排序
int ans=0,t=-1;//令t=-1可以使第一个区间与其他区间操作相同
for(int i=1;i<=n;i++)
if(a[i].begin>=t){ans++;t=a[i].end;}
cout<<ans<<endl;
return 0;
}
7.P1031均分纸牌
题意:有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。
现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。
分析:求总张数--->求平均数--->求各堆纸牌与平均数的差值--->左往右加(注意去除前导后导0,及中间0的判断)
AC代码:
#include<bits/stdc++.h>
using namespace std;
int a[110];
int main()
{
int n,ave=0;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
ave+=a[i];//求总张数
}
ave/=n;//求平均数
for(int i=1;i<=n;i++)
a[i]-=ave;//求每堆纸牌与平均数差值
int i=1,j=n,step=0;
while(a[i]==0&&i<n)i++;
while(a[j]==0&&j>1)j--;//去除前导后导0
while(i<j)
{
a[i+1]+=a[i];//将第i堆纸牌移到第i+1堆上
a[i]=0;//第i堆牌移走后变为0
step++;//计步数
i++;//对下一堆纸牌进行循环操作
while(a[i]==0&&i<j)i++;//过滤移牌过程中产生的0
}
cout<<step<<endl;
return 0;
}
8,P1080国王游戏
题意:恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 n 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。国王不希望某一个大臣获得特别多的奖赏,所以他想请你帮他重新安排一下队伍的顺序,使得获得奖赏最多的大臣,所获奖赏尽可能的少。注意,国王的位置始终在队伍的最前面。
输入格式:第一行包含一个整数 n,表示大臣的人数。第二行包含两个整数 a和 b,之间用一个空格隔开,分别表示国王左手和右手上的整数。接下来 n 行,每行包含两个整数 a 和 b,之间用一个空格隔开,分别表示每个大臣左手和右手上的整数。
输出格式:输出只有一行,包含一个整数,表示重新排列后的队伍中获奖赏最多的大臣所获得的金币数。
分析:(抄袭)我们对于国王身后的两个点来分析
队列可能是这样的:
*
Left
Right
king:
a0
b0
p1
a1
b1
p2
a2
b2
那么我们计算可得ans1 =max(b