POJ 1324 Holedox Moving

来源:互联网 发布:淘宝商品条形码怎么填 编辑:程序博客网 时间:2024/06/05 14:42

Name: Holedox Moving
P_ID: POJ 1324
题目链接:http://poj.org/problem?id=1324

题意描述:
n*m(最大20)的迷宫,l长(不超过8)的贪吃蛇,蛇身可弯曲,出口在(1,1),不能走石头所在格子,求蛇身最少移动次数。

题目分析:
题目本身是要考bfs最短路这个很明确,唯一不寻常的是在蛇移动过程中蛇身也在动。刚开始我认为这道题并没有什么特别的地方,于是采用了很普通的一种想法:
正常对头到(1,1)进行bfs,每次状态,我判断头周围的格子,当既不是石头,也不是蛇身的时候,说明这个格子是可以走的,我进行如下三个操作:
1. 蛇身移动一格(依次前移,蛇头新位置入队)
2. 将新的蛇头所在位置vis标记为1
3. 原蛇尾位置标记为空(代表可走)
下面是我的代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>using namespace std;typedef long long ll;const int MOD = 1e9 + 7;const int MAXN = 1e5 + 3;int n, m, l, b;int num = 0;char maze[25][25];int vis[21][21];const int dir[][2] = {{0,1}, {0,-1}, {1,0}, {-1,0}};struct cell {    int x;    int y;    cell(int a, int b)    {        x = a;        y = b;    }};struct node {    int x;    int y;    int step;    vector<cell> myBody;};int flag = 0;vector<cell> myBody;bool check(int x, int y){    if(x<1 || x>n || y<1 || y>m) return false;    if(maze[x][y]=='L' || maze[x][y]=='X') return false;    return true;}void moveWork(int xx, int yy, vector<cell> &a){    for(int i=a.size()-1; i>0; --i)     {        a[i].x = a[i-1].x;        a[i].y = a[i-1].y;    }    a[0].x = xx;    a[0].y = yy;}int bfs(){    node first;    first.x = myBody[0].x;    first.y = myBody[0].y;    first.step = 0;    first.myBody = myBody;    queue<node> myPath;    myPath.push(first);    while(!myPath.empty())    {        node now = myPath.front();        myPath.pop();      //  cout << now.x << "," << now.y << "---" << now.step << endl;        if(now.x==1 && now.y==1) return now.step;        for(int i=0; i<4; ++i)        {            int xx = now.x + dir[i][0];            int yy = now.y + dir[i][1];            if(check(xx, yy) && !vis[xx][yy])            {                vector<cell> mmBody = now.myBody;                moveWork(xx, yy, mmBody);                node next;                next.x = xx;                next.y = yy;                next.step = now.step + 1;                next.myBody = mmBody;                myPath.push(next);                vis[xx][yy] = 1;                flag = 1;           }        }        int p = now.myBody[l-1].x;        int q = now.myBody[l-1].y;        maze[p][q] = '.';        flag = 0;    }    return -1;}int main(){    while(scanf("%d%d%d", &n, &m, &l))    {        flag = 0;        num++;        if(n==0 && m==0 & l==0) break;        memset(maze, '.', sizeof(maze));        memset(vis, 0, sizeof(vis));        while(!myBody.empty()) myBody.clear();        for(int i=0; i<l; ++i)        {            int x;            int y;            scanf("%d%d", &x, &y);            maze[x][y] = 'L';            myBody.push_back(cell(x,y));        }        scanf("%d", &b);        for(int i=0; i<b; ++i)        {            int x;            int y;            scanf("%d%d", &x, &y);            maze[x][y] = 'X';        }        int ans;        ans = bfs();        if(ans==-1) printf("Case %d: -1\n", num);        else printf("Case %d: %d\n", num, ans);    }    return 0;}

交上去的下场是:
Wrong Answer

为什么呢?

刚刚我的代码中,vis所记录的是一个二维数组,只标记了迷宫本身,也就是说我保证蛇头不走重复的路,但是,事实上这是不对的。因为有一些情况下蛇是需要走一些路途把身体甩过去,然后回过头才可能有路能出到出口去,这种情况下蛇头就必然会有重复的迷宫位置需要去走。

此外,可能甚至有一些情况下:蛇通过重复走同一个位置,把蛇身甩过去,比直接不走重复位置到出口所需步数更加少。

这个问题我居然一直没有想到,直到看了http://blog.csdn.net/u013480600/article/details/25336473
的题解才发现这个问题。
因此,为了解决这个问题,我们的vis数组就不能只有二维了。而是需要第三维,用来存储蛇身的弯曲状态。

[参考AC代码]

/** * Name: Gluttonous Snake * P_ID: POJ_1324 * date: 2016-04-27 * note: bit operation + status memory * */#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>using namespace std;typedef long long ll;const int MOD = 1e9 + 7;const int MAXN = 1e5 + 3;int n, m, l, b;int num = 0;char maze[25][25];int vis[21][21][1<<14];const int dir[][2] = {{1,0}, {0,-1}, {-1,0}, {0,1}};int d[10];struct cell {    int x;    int y;    cell(int a, int b)    {        x = a;        y = b;    }};struct node {    int x;    int y;    int step;    int status;    node(int a, int b, int c, int d)    {        x = a;        y = b;        step = c;        status = d;    }};int flag = 0;bool check(int x, int y, node temp){    if(x<1 || x>n || y<1 || y>m) return false;    if(maze[x][y]=='X') return false;    for(int i=l-1; i>=1; --i)    {        d[i] = temp.status&3;        temp.status>>=2;    }    int xx = temp.x, yy = temp.y;    for(int i=1; i<l; ++i)    {        xx+=dir[d[i]][0];        yy+=dir[d[i]][1];        if(xx==x && yy==y) return false;    }    return true;}int bfs(node &start){    vis[start.x][start.y][start.status] = num;    queue<node> myPath;    myPath.push(start);    while(!myPath.empty())    {        node now = myPath.front();        myPath.pop();      //  cout << now.x << "," << now.y << "---" << now.step << endl;        if(now.x==1 && now.y==1) return now.step;        int nx = now.x;        int ny = now.y;        int ns = now.status;        int np = now.step;        for(int i=0; i<4; ++i)        {            int xx = nx + dir[i][0];            int yy = ny + dir[i][1];            if(xx==1 && yy==1) return np+1;            int nst = (ns>>2) + (((i+2)%4)<<(2*(l-2)));            if(check(xx, yy, now) && vis[xx][yy][nst]!=num)            {                myPath.push(node(xx, yy, np+1, nst));                vis[xx][yy][nst] = num;            }        }    }    return -1;}int main(){    while(scanf("%d%d%d", &n, &m, &l))    {        flag = 0;        num++;        if(n==0 && m==0 & l==0) break;        memset(maze, '.', sizeof(maze));        int x, y;        scanf("%d%d", &x, &y);        node first(x,y,0,0);        int nx, ny;        for(int i=1; i<l; ++i)        {            scanf("%d%d", &nx, &ny);            for(int j=0; j<4; ++j)            {                if(x+dir[j][0]==nx && y+dir[j][1]==ny)                {                    first.status = (first.status<<2) + j;                    break;                }            }             x = nx;            y = ny;        }        scanf("%d", &b);        for(int i=0; i<b; ++i)        {            int x;            int y;            scanf("%d%d", &x, &y);            maze[x][y] = 'X';        }        int ans;        ans = bfs(first);        if(ans==-1) printf("Case %d: -1\n", num);        else printf("Case %d: %d\n", num, ans);    }    return 0;}
0 0
原创粉丝点击