返回顶部

2017, X Samara Regional Intercollegiate Programming Contest E. Bonuses and Teleports (思维,模拟)

  • 题意:在\(x\)轴上有很多传送点和钻石,当位于传送点上时,可以传送到其他任意传送点(不记操作数),位于钻石上时可以吃掉它,每次可以移动一个单位,问最少多少次可以吃掉所有的钻石.

  • 题解:对于某个位置上的钻石,我们可以从它左边的传送点走过来,或者从它右边的传送点走过来,又或者从上一个钻石的位置直接走过来,我们每次在这三个距离中取最小即可.具体怎么实现呢?我们首先考虑左右传送点的情况,遍历每个钻石的位置,然后记录当前这个钻石到左传送点或右传送点的最小距离,之后再次遍历钻石位置,比较\(上个钻石走回传送门的距离加上从传送门走到当前钻石的最小距离\)\(上个钻石的位置直接走到当前位置的距离\),取\(min\)贡献给答案即可.

  • 代码:

    int n,m;
    ll t[N],b[N];
    ll c[N];
    ll res;
     
    int main() {
        //ios::sync_with_stdio(false);cin.tie(0);
        scanf("%d %d",&n,&m);
     
        for(int i=1;i<=n;++i){
            scanf("%lld",&t[i]);
        }
        for(int i=1;i<=m;++i){
            scanf("%lld",&b[i]);
        }
     
        b[0]=b[m+1]=t[1];
        t[n+1]=INF;
        int j=0;
        ll tmp;
        for(int i=1;i<=m;++i){       //求两个tele之间到钻石的min
            while(t[j+1]<=b[i]) j++;
            if(j==0) c[i]=INF;
            else c[i]=b[i]-t[j];
            if(j<n) tmp=t[j+1]-b[i];
            else tmp=INF;
            c[i]=min(c[i],tmp);
        }
     
        c[0]=c[m+1]=0;
        for(int i=1;i<=m+1;++i){
            ll dis=abs(b[i]-b[i-1]);
            dis=min(dis,c[i-1]+c[i]);
            res+=dis;
        }
     
        printf("%lld\n",res);
     
        return 0;
    }
    
posted @ 2020-08-14 12:24  _Kolibri  阅读(242)  评论(0)    收藏  举报