提升coding能力------搜索专题(8)-----poj 1324

pku 1324 Holedox Moving
题目地址:
 http://acm.pku.edu.cn/JudgeOnline/problem?id=1324

题目大意:

给你一个由小方格构成的“蛇身”,对蛇的头部和身子部分进行了排号,终点为矩阵左上角的第一个点,矩阵中有的点被标记了不可访问点,问蛇是否能通过移动进而使蛇头到达终点,如果可以的话,输出所要的最小步数。

具体分析:

简单点一下,以后会具体分析。这边蛇的移动的本质,就是后面的点替代前面的点的过程。还有一个最难的地方,就是如何存储蛇的状态,避免BFS重复搜索,避免TLE,如果用数组存储蛇身的话,在判断现在位置的蛇是否出现的话,会出现超时,所以要用状态压缩来存储蛇的状态,然后BFS。

AC代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define N 25
bool vis[N][N][1<<14];
int dirc[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};
int s_x[N],s_y[N];
int Map[N][N];
int n,m,k,l,ans;
struct Node
{
    int x, y;
    int sum;
    int cnt;
    Node(int x = 0):cnt(x){}
};
int get_dirc(int x ,int y)
{
    if(x == 1&& y ==0)
        return 0;
    if(x == -1 && y== 0)
        return 1;
    if(x==0 && y== -1)
        return 2;
    if(x == 0 && y== 1)
        return 3;
}
int check(Node& T, int pos_x, int pos_y)
{
    int sum ,temp, x, y;
    sum = T.sum;
    x = T.x;
    y = T.y;
    
    for(int i= 1 ;i <l ;i++)//坑点在这里,由于最后一个点被遗弃,新的蛇头点可以占用其位置,并不用一定要与之不同
    {
        temp = sum&3;
        sum >>=2;
        x += dirc[temp][0];
        y += dirc[temp][1];

       // printf("(%d %d)\n",x ,y);
        if(pos_x== x && pos_y== y)
            return 0;

    }

    T.sum = T.sum %( 1 << ((l-1-1)*2) );

    T.sum = T.sum*4 + get_dirc(T.x - pos_x, T.y - pos_y);

    T.x = pos_x;
    T.y = pos_y;
    if(vis[T.x][T.y][T.sum])
        return 0;

    vis[T.x][T.y][T.sum] =1;
    T.cnt++;

    return 1;


}
void BFS(Node& T)
{
    queue<Node> q;
    Node temp,Front;

    temp = Front = T;
    q.push(temp);

    while(!q.empty())
    {

        Front = q.front();
        q.pop();
        if(Front.x == 1 && Front.y == 1)
        {
            ans = Front.cnt;
            return ;
        }
        for(int i =  0 ;i < 4 ;i++)
        {
            temp = Front;
            int x = temp.x + dirc[i][0];
            int y = temp.y + dirc[i][1];
            if(x>=1 && x<=n && y>=1 && y<=m && !Map[x][y]&& check(temp,x,y))
                q.push(temp);

        }
    }

    return ;


}

int main()
{
    int Case = 0;

    while(cin >> n >> m >> l)
    {


        if(!n && !m && !l)
            break;
        Case++;
        ans = -1;
        memset(Map,0,sizeof(Map));
        memset(vis,false,sizeof(vis));
        for(int i = 0 ;i < l ;i++)
            cin >> s_x[i] >> s_y[i];

        int sum = 0;
        for(int i = l-1 ; i >=1 ; i--) //4进制方向转化为10进制方向进行存储
            sum = sum*4 + get_dirc(s_x[i] - s_x[i-1], s_y[i] - s_y[i-1]);

        cin >> k;
        int a, b;
        for(int i = 0 ;i < k  ;i++)
        {
            cin >> a >> b;
            Map[a][b] = 1;
        }
        Node First;
        First.x = s_x[0] , First.y = s_y[0];
        First.sum = sum;
        vis[First.x][First.y][sum] =1;

        BFS(First);
        printf("Case %d: %d\n",Case,ans);





    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/CCSGTC/article/details/82257108
今日推荐