1. 程式人生 > 實用技巧 >2017, X Samara Regional Intercollegiate Programming Contest E. Bonuses and Teleports (思維,模擬)

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;
    }