提升coding能力------搜索專題(7)-----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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章