1. 程式人生 > >Vasya and Robot CodeForces - 1073C (經典走方格問題+二分)

Vasya and Robot CodeForces - 1073C (經典走方格問題+二分)

題意:機器人從起點(0,0)開始,每次只能向上,下,左,右進行移動,給出一個移動序列,問你通過修改這個移動序列,可以讓機器人走到(x,y)點的最小修改量(最小修改量定義為:修改的最大編號-最小編號+1)。

思路:將能否走到(x,y)轉化為偏移量能否從 0到 x,0到y.

       我們先模擬一下他給出的移動序列,記錄這個序列產生偏移量的字首和,有了字首和,我們就可以知道任意區間對結果的偏移量貢獻。

下面我們列舉修改長度:它的意思是,我們選取的那個區間,可以隨意改動,因為我們只關心這個區間的起點和終點,具體內部如果變化,我們並不關心。

列舉長度使用2分來做,在check()函式裡,我們計算出除去這個區間以後,已經走的偏移量,再看這個區間的長度能否滿足還需要的偏移量。

還有一個問題是,如果列舉的區間長度大於所需的,那麼超出部分一定是偶數,這是走方格問題的一個性質。

程式碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
int n;
int sx[maxn],sy[maxn];
int x,y;
bool check(int len)
{
    for(int i=1;i+len<=n+1;i++)
    {
        int tmpx=x,tmpy=y;
        int subx=sx[n]-sx[i+len-1];//最後幾步走的,先減回來
        int suby=sy[n]-sy[i+len-1];
        tmpx-=subx;//前面走的
        tmpy-=suby;
        int addx=sx[i-1]-sx[0];//還需要的
        int addy=sy[i-1]-sy[0];
        if(abs(tmpx-addx)+abs(tmpy-addy)<=len&&(len-abs(tmpx-addx)-abs(tmpy-addy))%2==0)
        {
            return 1;
        }
    }
    return false;
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    scanf("%d",&n);
    string s;
    cin>>s;
    scanf("%d%d",&x,&y);
    sx[0]=0,sy[0]=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='U')
        {
            sy[i+1]=sy[i]+1;
            sx[i+1]=sx[i];
        }
        else if(s[i]=='D')
        {
            sy[i+1]=sy[i]-1;
            sx[i+1]=sx[i];
        }
        else if(s[i]=='R')
        {
            sx[i+1]=sx[i]+1;
            sy[i+1]=sy[i];
        }
        else if(s[i]=='L')
        {
            sx[i+1]=sx[i]-1;
            sy[i+1]=sy[i];
        }
    }
    int l=0,r=n;
    int ans=-1;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))
        {
            r=mid-1;
            ans=mid;
        }
        else
        {
            l=mid+1;
        }
    }
    printf("%d\n",ans);
    return 0;
}