T2963 Snake [BFS, quaternary-like pressure, A *]

Judge Online : Unknown

The Label : BFS, quaternary-like pressure, violence, A *, hash, metaphysics.

Title Description

Given an initial position n * m and snake map, the map location of some stones, the snake can not pass. Of course, the snake can not climb beyond the map.

Every move, snakeheads first move, then each section of the body to reach a position on the body is located. Smugglers will go where there are not other parts of the body.

A minimum number of steps required to move the snake reaches the (1,1) point.

FIG. B1 is the snakehead, B4 is the tail, the second picture is the first picture after the effect step movement of the snake, stone black areas.

Entry

The first line of three integers n, m, K, K represents the length of the snake.

The next K lines of two integer representing the coordinates of each section of the body of a snake, the snake tail turn from smugglers to coordinate the row and column number.

A second row K + 2 integer s, is the number of stones. Next s lines of two integers, denotes a stone row number and column number. Stone does not appear in (1,1).

Export

Output smugglers minimum number of steps, you can reach the (1,1) point. If you can not reach, output -1.

Sample

Input

4 4 1
3 3
2
2 2
2 3

5 5 2
3 3
3 2
4
2 2
2 3
3 4
4 2

5 6 4
4 1
4 2
3 2
3 1
3
2 3
3 3
3 4

4 4 4
2 3
1 3
1 4
2 4
4
2 1
2 2
3 4
4 2

Output

4

8

9

-1

Hint

For 30% of the data, K = 1;
for 60% of the data, 1≤K≤3, n and m range [2, 10];
100% data, 1≤K≤8, n and m range [2,20];

answer

Since n, m the same order, the following description when the time complexity of the algorithm used unified n.

30pts

Is the common BFS. Time complexity is \ (O (N ^ 2) \) .

#include<bits/stdc++.h>
using namespace std;
 
const int dx[]={-1,1,0,0};
const int dy[]={0,0,-1,1};
 
int n,m,k,mark[22][22];
struct node{int x,y;};
queue<node>q;
namespace p30{
    int dis[22][22];
    void bfs(int sx,int sy){
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)dis[i][j]=-1;
        q.push((node){sx,sy});
        dis[sx][sy]=0;
        while(!q.empty()){
            node now=q.front();q.pop();
            int x=now.x,y=now.y; 
            if(x==1&&y==1)break;
            for(int i=0;i<=3;i++){
                int nx=x+dx[i],ny=y+dy[i];
                if(nx<1||ny<1||nx>n||ny>m||mark[nx][ny])continue;
                if(dis[nx][ny]==-1){
                    dis[nx][ny]=dis[x][y]+1;
                    q.push((node){nx,ny});
                }
            }
        }
        printf("%d\n",dis[1][1]);
    }
    void solve(){
        int sx,sy;scanf("%d%d",&sx,&sy);
        for(int i=1;i<k;i++){
            int x,y;scanf("%d%d",&x,&y);
        }
        int tmp;scanf("%d",&tmp);
        for(int i=1;i<=tmp;i++){
            int x,y;scanf("%d%d",&x,&y);
            mark[x][y]=1;
        }
        bfs(sx,sy);
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&k); 
    p30::solve();
}

60pts

As the body only a maximum of three sections. State may directly record the position of each segment \ ([X1] [Y1] [X2] [Y2] [X3] [Y3] \) . Then transfer direct violence to coordinate the move your body.

The above looks more hanging space, so do not directly \ (dis [x1] [y1 ] [x2] [y2] [x3] [y3] \) this array, engage in the structure in.

struct node{int x[3],y[3];};

Due to the wide use of the state searchshouldNot too much, the space is less likely to get caught out. And the time is approximately \ (O (N ^ K) = O (N ^. 6) \) .

//如果把下面结构体里的x[],y[]开大,其实可以过掉这道题qwq。
#include<bits/stdc++.h>
using namespace std;
const int rx[]={-1,1,0,0},ry[]={0,0,-1,1};
int n,m,k,s;
bool mark[25][25];
struct node{
    int x[3],y[3],step;
}A;
queue<node>Q;
bool check(int x,int y){
    return x>=1&&x<=n&&y>=1&&y<=m&&!mark[x][y];
}
int bfs(){
    Q.push(A);
    node now,nxt;
    while(!Q.empty()){
        now=Q.front();
        Q.pop();
        if(now.x[0]==1&&now.y[0]==1)return now.step;
        for(int i=0;i<4;i++){
            bool flag=0;
            int X=now.x[0]+rx[i],Y=now.y[0]+ry[i];
            for(int j=0;j<k;j++)
                if(X==now.x[j]&&Y==now.y[j])flag=1;
            if(flag)continue;
            if(check(X,Y)){
                for(int j=1;j<k;j++){
                    nxt.x[j]=now.x[j-1];
                    nxt.y[j]=now.y[j-1];
                }
                nxt.step=now.step+1;
                nxt.x[0]=X,nxt.y[0]=Y;
                Q.push(nxt);
                mark[X][Y]=1;
            } 
        }
    }
    return -1;
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<k;i++)scanf("%d%d",&A.x[i],&A.y[i]);
    scanf("%d",&s);
    for(int i=1;i<=s;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        mark[x][y]=1;
    }
    A.step=0;
    mark[A.x[0]][A.y[0]]=1;
    printf("%d\n",bfs());
    return 0;
}

100pts

If the structure's upper opening array to k = 8, then a hash look or A * to optimize the like, may be had,And faster than the following solution

Record coordinate take too much space each segment of the body.

He observed that the body is attached to the (nonsense), It is possible to record like this, 第二段在第一段的哪个方位. So that only the four directions can be used quaternary shaped pressure .

The following code: i. I + 1 on the left: 0, i i + 1 in the top: 1, i i + 1 in the right: 2, i i + 1 in the bottom: 3.


BFS BFS still is, a major shift on a bit of trouble, attention to detail.

code show as below:

/*
  1
0[]2
 3
*/
#include<bits/stdc++.h>
#define N 22
using namespace std;
const int dx[]={-1,1,0,0},dy[]={0,0,-1,1},Turn[]={3,1,2,0};
int n,m,k,mark[N][N];
int pw[10],dis[N][N][16500];
inline int gonxt(int S,int di){return S*4%pw[k-1]+Turn[di];}
//移动后,更新状态
inline bool boom(int x,int y,int S,int di){
//会撞到自己时返回1
    int nx=x+dx[di],ny=y+dy[di];    
    for(register int i=1;i<k;++i){
        int o=S-S/4*4;S/=4; 
        if(o==0)y--;if(o==1)x--;if(o==2)y++;if(o==3)x++;
        if(x==nx&&y==ny)return 1;
    }
    return 0;
}
struct node{int x,y,S;}q[6600000];

inline int bfs(int sx,int sy,int fir){  
    memset(dis,-1,sizeof(dis));
    int head=1,tail=0;
    q[++tail]=((node){sx,sy,fir});dis[sx][sy][fir]=0;
    while(head<=tail){
        node now=q[head];head++;
        int x=now.x,y=now.y,S=now.S;    
        if(x==1&&y==1)return dis[x][y][S];
        for(register int i=0;i<=3;++i){
            int nx=x+dx[i],ny=y+dy[i];
            if(nx<1||ny<1||nx>n||ny>m||mark[nx][ny]||boom(x,y,S,i))continue;
            int T=gonxt(S,i);               
            if(dis[nx][ny][T]==-1){
                dis[nx][ny][T]=dis[x][y][S]+1;
                q[++tail]=(node){nx,ny,T};
            }
        }
    }
    return -1;  
}
int main(){
    register int sx,sy,x,y,lstx,lsty,S=0,tmp,i,v[9];
    scanf("%d%d%d",&n,&m,&k);   
    pw[0]=1;
    for(i=1;i<=9;++i)pw[i]=pw[i-1]*4;
    scanf("%d%d",&sx,&sy);lstx=sx,lsty=sy;
    
    for(i=1;i<k;++i){
        scanf("%d%d",&x,&y);
        if(x!=lstx)v[i]=(x==lstx-1)?1:3;
        else v[i]=(y==lsty-1)?0:2;
        lstx=x,lsty=y;
    }
    for(i=k-1;i>=1;i--)S=S*4+v[i];
    //初始状态(sx,sy,S)
    scanf("%d",&tmp);
    for(i=1;i<=tmp;++i)scanf("%d%d",&x,&y),mark[x][y]=1;
    
    cout<<bfs(sx,sy,S);
}

Guess you like

Origin www.cnblogs.com/Tieechal/p/11606466.html