排序不等式
【分析】
1.结构体排序(sort的运用:
头文件<algorithm> -> 定义cmp -> sort(first,last,cmp))
2.总时间不包括当前接水的时间
3.接水时间越短的在越前面
【代码】
#include <bits/stdc++.h>
using namespace std;
struct s{
int time;
int num;
}a[1005];
int n,t,sum,ans;
bool cmp(s a1,s a2){
return a1.time<a2.time;
}//定义结构体变量需要引用结构体名称
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].time;
a[i].num=i;
}
/*
for(int i=1;i<n;i++){
for(int j=1;j<=n-i;j++){
if(a[j].time>a[j+1].time){
swap(a[j].time,a[j+1].time);
swap(a[j].num,a[j+1].num);//冒泡排序,可以直接swap(a[j],a[j+1])
}
}
}*/
sort(a+1,a+n+1,cmp); //结构体排序可以用sort
for(int i=1;i<=n;i++){
cout<<a[i].num<<" ";
}
cout<<endl;
sum=a[1].time;
for(int i=2;i<=n;i++){
ans+=sum;
sum+=a[i].time;
}
//cout<<ans;
printf("%.2lf",(double)ans/n);
return 0;
}
【分析】
1.负数可以计算,即当纸牌数小于均值时,a[i]-ave为负数,令a[i+1]加上负数相当于a[i+1]将差值分给了a[i],仍能得到均值
2.纸牌数与均值相等时跳过
【代码】
#include <bits/stdc++.h>
using namespace std;
int a[105];
int main(){
int n,ave,ans=0,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];//计算总值
}
ave=sum/n;//计算均值
for(int i=1;i<=n;i++){
if(a[i]==ave) continue;//纸牌数与均值相等时可直接跳过
else{
a[i+1]+=a[i]-ave;//不相等时 将剩余的数分到下一个数
ans++;//次数增加
}
}
cout<<ans;
return 0;
}
【分析】
1.双层循环,第一个表明要删去s个值,每一次循环删去找到的第一个峰值,即第一个大于后面的数
2.边界问题,详见代码
3.处理前导0,但必须保留最后一位0
【代码】
#include <bits/stdc++.h>
using namespace std;
string a;//定义字符串
int main(){
cin>>a;
int l,k,s;
cin>>s;
l=a.size();//取整数的长度
for(int i=1;i<=s;i++){//需要删去s个数
for(int j=0;j<=l-i;j++){//j从0开始遍历,而i从1开始,实际遍历到l-i位即可,不需要考虑后面的位数
if(a[j]>a[j+1]){
k=j;//删去第一个峰值
break;
}
}
//cout<<k<<" "<<a[k]<<endl;
for(int j=k;j<=l-i;j++){
a[j]=a[j+1];//将删去后剩余的每一位向前挪
}
}
k=0;//这里的k作下标
while(a[k]=='0'&& k!=l-1-s) k++;//处理前导0
for(int i=k;i<=l-1-s;i++){//从0开始 最后一位的下标是l-1 再减去删去的s个数
cout<<a[i];
}
return 0;
}
【分析】
1.第一发能达到任意高度,即假设为1e9
2. 以后每一发炮弹都不能高于前一发的高度,则令拦截成功的导弹为1,并更新下一次拦截的最高高度,然后配备新的拦截系统拦截为0的导弹
【代码】
#include <bits/stdc++.h>
using namespace std;
int a[1005];
int main(){
int k;
int l=1;
a[l]=1e9;//假设第一套系统的拦截高度为无限大
while(cin>>k){
int flag=0;
for(int i=1;i<=l;i++){
if(k<=a[i]){
a[i]=k;
flag=1;//已拦截的导弹标记为1 并且更新系统拦截高度
break;
}
}
if(flag==0){
l++;//对于没有拦截的导弹需要配备新的系统
a[l]=k;//设置新的拦截系统高度为k
}
}
cout<<l;
return 0;
}
区间问题
【分析】
1.先结束的先安排,安排的起始时间必须在空闲时间内
2.结构体排序(同上1319)
【代码】
#include <bits/stdc++.h>
using namespace std;
struct s{
int l;
int r;
}a[100005];//定义结构体
bool cmp(s a1,s a2){
return a1.r<a2.r;
}//定义cmp函数
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
}
sort(a+1,a+n+1,cmp);//排序
int kt,ans=0;
for(int i=1;i<=n;i++){
if(i==1){
kt=a[i].r;
ans++;
}//安排第一个活动 令kt等于第一个活动的结束时间
else{
if(kt<=a[i].l){//如果下一个活动的起始时间大于kt
kt=a[i].r;
ans++;//继续安排
}
}
}
cout<<ans<<endl;
return 0;
}
【分析】
首先按右端点的大小从小到大排序(sort),并每次标记当前区间的右端点为k,下一个区间的左端点如果在k前面或与k重合,则不需要考虑;如果在k后面,则令其右端点为新的k。
【代码】
#include <bits/stdc++.h>
using namespace std;
struct s{
int l,r;
}a[10005];
int cmp(s a1,s a2){
return a1.r<a2.r;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i].l>>a[i].r;
}
sort(a,a+n,cmp);
int k=-1,ans=0;
for(int i=0;i<n;i++){
if(a[i].l>k){//如果下一个区间的左端点大于k
k=a[i].r;//令k等于该区间的右端点
ans++;//计数
}//循环比较
}
cout<<ans;
return 0;
}