题意:
给定长度L的轴,轴上有n个点,n个点可以向左右走,左到0,右到L+1,且两个点如果相向而走,碰面后都会转身离开
问这些点全部离开独木桥所需的最大和最小时间(每个点运动的速度为1m/s)
分析:
1,简单模拟题,最小的话,我想的是对每个点到桥两边距离取最小,之后再对这些值取最大即可;
2,这题比较有意思,刚开始我分析这个题选取最大是用最左边的点和最右边的点,他们遇到之后再相互转身离开,这样二者取最大,但是会wa一个点
其实,相互转身离开可以看作是两个点交换灵魂之后继续向前走,因为他们的速度都没有变化,所以只需要对每个点到两边的距离取最大值即可。
反思:
1,从我的错误想法看,如果两个点中间距离为偶数,这样想应该是不会出错,但如果是奇数就牵扯到把一个长度为1的格子分成两个处理,这样处理起来会很麻烦;
2,显然把他们抽象成交换灵魂就会很好理解,直接取一个最大值即可。
3,遇到这种简单模拟题,从我自己的惯性思路来说,总是喜欢硬生生的模拟,如果模拟的条件很多的话,容易写题写自闭,有时候和答案仅仅一步之遥......很难将这种问题抽象为某一个很简单的式子,再看完别人的代码之后,有种我为什么这么蠢的感觉,不仅仅是这一个问题,还有cf比赛时候,总是将简单的问题复杂化,可能是因为还没有养成这种算法思维,慢慢积累吧。
代码:
1,错误版本,会wa第一个点,其他点都会过,有时间改改(逃
#include<bits/stdc++.h> const int maxn=5e3+10; const int inf=0x3f3f3f3f; typedef long long ll; using namespace std; int a[maxn]; int main() { int L,n; cin>>L>>n; int ma=0,mi=0; for(int i=1; i<=n; i++) { cin>>a[i]; mi=max(mi,min(L+1-a[i],a[i]-0)); } sort(a+1,a+1+n); int tmp=(a[n]-a[1])/2; int ans=a[n]-tmp; int ans1=a[1]+tmp; ma=max(max(L+1-ans1,ans1),max(L+1-ans,ans)); cout<<mi<<" "<<ma+tmp<<endl; }
2,正确版本
#include<bits/stdc++.h> const int maxn=5e3+10; const int inf=0x3f3f3f3f; typedef long long ll; using namespace std; int a[maxn]; int main() { int L,n; cin>>L>>n; int ma=0,mi=0; for(int i=1; i<=n; i++) { cin>>a[i]; mi=max(mi,min(L+1-a[i],a[i]-0)); ma=max(ma,max(L+1-a[i],a[i]-0)); } cout<<mi<<" "<<ma<<endl; }