POJ 1101 The Game

来源:互联网 发布:淘宝上怎么上下架 编辑:程序博客网 时间:2024/04/29 14:44

/*

http://acm.pku.edu.cn/JudgeOnline/problem?id=1101

这道题主要采用BFS的变体版本,核心在于:

1)除了需要在队列中保存当前节点的方向,坐标外,还需要保存到达当前节点所需的segment数;

2)需要使用一个全局minSeg来记录到达某个节点所需的最少segment数,当新的seg <= minSeg时,这个新状态才

入队列。只保留seg <= minSeg的原因的证明:假设对节点x,y 当seg = minSeg[x][y] + 1, 假设当前方向为d1, 最优的minSeg的方向

为d2, 如果d1 == d2,则新seg肯定不是最优的,当d1 != d2, 最优的minSeg[x][y]需要调转一步方向才能和seg方向一致,即

需要minSeg[x][y] + 1个segment, 和seg相同,即没有更优,所以不需要保存!如果不加上这个条件,会状态爆炸

 

*/

#include <iostream>
#include <memory>
#define MAX_N 75
#define Q_SIZE 10000


using namespace std;

char map[MAX_N + 5][MAX_N + 5];

int queue[Q_SIZE + 5][4];  //dir up:0, down:1, left:2, right:3
int dir[4][2] = {{-1, 0}, {1, 0}, {0, - 1}, {0, 1}};
int head, tail;

int minSeg[MAX_N + 5][MAX_N + 5];
int w, h, x1, y1, x2, y2;
int minLen = INT_MAX;

void initSeg()
{
    int i, j;
    for(i = 0; i <= h + 1; i++)
        for(j = 0; j <= w + 1; j++)
            minSeg[i][j] = INT_MAX;    
}

bool inRange(int x, int y)
{
    return (x >= 0 && x <= h + 1 && y >= 0 && y <= w + 1 && (map[x][y] == ' ' || (x == x2 && y == y2)));
}
void bfs()
{
    head = tail = 1;
    queue[tail][0] = x1;
    queue[tail][1] = y1;
    queue[tail][2] = -1;
    tail = tail % Q_SIZE + 1;
    queue[tail][3] = 0;

    int curX, curY, newX, newY, curDir, curSeg, newSeg;
    while(head != tail)
    {
        curX = queue[head][0];
        curY = queue[head][1];
        curDir = queue[head][2];
        curSeg = queue[head][3];

        head = head % Q_SIZE + 1;
                
        if(curX == x2 && curY == y2)
        {
            if(curSeg < minLen)
                minLen = curSeg;
            continue;
        }

        for(int d = 0; d < 4; d++)
        {
            newX = curX + dir[d][0];
            newY = curY + dir[d][1];
            if(newX == x1 && newY == y1)
                continue;
            if(inRange(newX, newY))
            {
                if(curDir == -1)
                    newSeg = 1;
                else
                {
                    if(curDir != d)
                        newSeg = curSeg + 1;
                    else
                        newSeg = curSeg;
                }
                if(newSeg <= minSeg[newX][newY])  //这个条件的使用原因见2)
                {
                    minSeg[newX][newY] = newSeg;
                    queue[tail][0] = newX;
                    queue[tail][1] = newY;
                    queue[tail][2] = d;
                    queue[tail][3] = newSeg;
                    tail = tail % Q_SIZE + 1;
                }
            }
        }

    }
}


int main()
{
    int i, j, seq = 0;
    char ch;
    while(cin>>w>>h && !(w == 0 && h == 0))
    {
        getchar();
        seq++;
        for(i = 0; i <= h + 1; i++)
        {
            for(j = 0; j <= w + 1; j++)
            {
                if(i >= 1 && i <= h && j >= 1 && j <= w)
                    ch = getchar();
                else
                    ch = ' ';
                map[i][j] = ch;
                if(i >= 1 && i <= h && j == w)
                    getchar();
            }
            
        }
        cout<<"Board #"<<seq<<":"<<endl;
        int qSeq = 0;
        while(cin>>y1>>x1>>y2>>x2 && !(x1 == 0 && y1 == 0 && x2 == 0 && y2 == 0))
        {
            minLen = INT_MAX;
            initSeg();
            bfs();
            qSeq++;
            cout<<"Pair "<<qSeq<<": ";
            if(minLen == INT_MAX)
                cout<<"impossible."<<endl;
            else
                cout<<minLen<<" segments."<<endl;
        }
        cout<<endl;
    }
    return 0;
}