P1007 独木桥
1.当士兵相遇时掉头,可以看作是穿过彼此(灵魂交换);
2.最小值即为士兵们最快返回时间的最大值;
3.最大值即为士兵们最慢返回的时间的最大值;
#include <bits/stdc++.h>
using namespace std;
int l,n,a,t,x,y;
int minn=0,maxn=0;
int main(){
cin>>l>>n;
for (int i=1;i<=n;i++){
cin>>a;
x=a-0; //找出往两边方向的时间
y=l-a+1;
if (x<y){ //排序
t=x;
x=y;
y=t;
}
if(x>maxn) maxn=x; //找出最慢返回时间的最大值
if(y>minn) minn=y; //找出最快返回时间的最大值
}
cout<<minn<<" "<<maxn;
return 0;
}
P1223 排队接水
1.想使等待时间最短,尽量使打水时间最短的先打水,如第一个人打水时间1min,则后面9人共等待1*9min,如果打水时间1000min,则后面9人共等待1000*9min;
2.第i个人打水时,后面还有(n-i)个人,共需等待(n-i)*Ti
#include <bits/stdc++.h>
using namespace std;
struct paidui{ //结构体记录打水时间和位置
int value;
int p;
} a[1010];
bool cmp(const paidui &a,const paidui &b){
if(a.value==b.value) return a.p<b.p;
else
return a.value<b.value;
}
int main(){
int n;
double sum=0;
cin>>n;
for(int i=1;i<=n;i++){ //初始化
cin>>a[i].value;
a[i].p=i;
}
sort(a+1,a+1+n,cmp); //按照打水时间排序
for (int i=1;i<=n;i++){
cout<<a[i].p<<" "; //输出位置
sum+=(n-i)*a[i].value;
}
cout<<endl;
printf("%.2lf",sum/n);
return 0;
}
P1803 凌乱的yyy / 线段覆盖
1.按照结束时间排序,再判断在此场比赛结束后最近时间的比赛立刻参加
#include <bits/stdc++.h>
using namespace std;
struct p{
int a; //a储存开始时间
int b; //b储存结束时间
}pp[1000005];
bool cmp(p x,p y){
return x.b<y.b;
}
int main(){
int n,t,ans=1;
cin>>n;
for (int i=1;i<=n;i++){
cin>>pp[i].a>>pp[i].b;
}
sort(pp+1,pp+1+n,cmp); //按照结束时间排序
t=pp[1].b;
for (int i=2;i<=n;i++){
if(pp[i].a>=t){ //若下一场比赛开始时间在上一场比赛结束时间之后
ans++; //参赛
t=pp[i].b; //更新结束时间
}
}
cout<<ans;
return 0;
}
P1031 [NOIP2002 提高组] 均分纸牌
1.负数向右移动,相当与右边的一堆牌向左移
#include <bits/stdc++.h>
using namespace std;
int a[10010],sum,j,ave,n,step,i=1;
int main(){
cin>>n;
for (i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
ave=sum/n; //算出平均数,即每堆最后的牌数
for (i=1;i<=n;i++){
a[i]=a[i]-ave; //算出差值,即还差几张,可以正负
}
i=1; j=n;
while(a[i]==0 &&i<n) i++; //过滤掉最左右端已经满足条件
while(a[j]==0 &&j>1) j-- ;
while(i<n){
a[i+1]+=a[i]; //把牌向右移
a[i]=0;
step++;
i++;
while(a[i]==0&&i<n) i++; //移牌后满足牌数的一堆跳过
}
cout<<step;
return 0;
}