[CF1236D] Alice and the Doll - 模拟,STL

与世无争的帅哥 提交于 2019-12-01 23:48:57

[CF1236D] Alice and the Doll

Description

\(N \times M\)网格,有 \(K\) 个格子里有障碍物。每次经过一个格子的时候只能直走或者右转一次。初态在 \((1,1)\) 格子向上。求是否存在一条路径经过所有无障碍格子恰好一次。

Solution

最优的走法是遇到障碍或者边界就右转,否则直走。

走过一排格子相当于挪动边界线。

这两个结论仔细品味起来很挺有深度的。

然后暴力模拟就可以了,找障碍物的过程可以用 set 优化。

这题的坐标系好像有点奇怪,SB的我就这么搞反坐标WA了一发。然后忘记开longlong又WA了一发。

Code
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;

int n,m,k,t1,t2,t3,t4,lx,ly,ux,uy,dir,ans=1;
set <int> sx[N],sy[N];

int FindIncX(int x,int y)
{
    return min(ux,*sy[y].lower_bound(x));
}

int FindDecX(int x,int y)
{
    return max(lx,*(--sy[y].lower_bound(x)));
}

int FindIncY(int x,int y)
{
    return min(uy,*sx[x].lower_bound(y));
}

int FindDecY(int x,int y)
{
    return max(ly,*(--sx[x].lower_bound(y)));
}

signed main()
{
    cin>>n>>m>>k;
    lx=0;
    ly=0;
    ux=n+1;
    uy=m+1;
    for(int i=1; i<=m; i++)
    {
        sy[i].insert(0);
        sy[i].insert(n+1);
    }
    for(int i=1; i<=n; i++)
    {
        sx[i].insert(0);
        sx[i].insert(m+1);
    }
    for(int i=1; i<=k; i++)
    {
        cin>>t1>>t2;
        sx[t1].insert(t2);
        sy[t2].insert(t1);
    }
    dir=0;
    int x=1,y=1;
    while(true)
    {
        int nx,ny;
        switch(dir)
        {
        case 0:
            nx=x;
            ny=FindIncY(x,y)-1;
            break;
        case 1:
            ny=y;
            nx=FindIncX(x,y)-1;
            break;
        case 2:
            nx=x;
            ny=FindDecY(x,y)+1;
            break;
        case 3:
            ny=y;
            nx=FindDecX(x,y)+1;
            break;
        }
        if(x==nx && y==ny)
        {
            dir=(dir+1)%4;
            switch(dir)
            {
            case 0:
                nx=x;
                ny=FindIncY(x,y)-1;
                break;
            case 1:
                ny=y;
                nx=FindIncX(x,y)-1;
                break;
            case 2:
                nx=x;
                ny=FindDecY(x,y)+1;
                break;
            case 3:
                ny=y;
                nx=FindDecX(x,y)+1;
                break;
            }
            if(x==nx && y==ny)
                break;
        }
        ans += abs(nx-x) + abs(ny-y);
        switch(dir)
        {
        case 0:
            lx=max(lx,nx);
            break;
        case 1:
            uy=min(uy,ny);
            break;
        case 2:
            ux=min(ux,nx);
            break;
        case 3:
            ly=max(ly,ny);
            break;
        }
        x=nx;
        y=ny;
    }
    //cout<<ans<<endl;
    if(ans==n*m-k)
    {
        cout<<"Yes"<<endl;
    }
    else
    {
        cout<<"No"<<endl;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!