【POJ3009 - Curling】 解題報告+思路+代碼+教訓(看別人的報告過的)

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#define INPUT
/**
Problem : poj3009
看別人的報告過得,代碼基本上相同,因爲實在不會了
Begin Time: 11th/3/2012 7:28 p.m.
End Time: 11th/3/2012 11:10 p.m.
解題報告:http://blog.csdn.net/harder2005/article/details/2816881
測試數據見Discuss
知識點:
    DFS,回溯,智商!!
教訓:
    這道題十分經典,簡直是“不動腦子就WA”的一道題的典範
    解題報告中的代碼十分簡潔精練,十分推薦!!
    1.關於搜索的選擇
        雖然是最短,但是題中說了超過10次就失敗,所以暗示了使用DFS
        這點跟那個Nightmare的思路是一樣的
    2.關於智商
        這道題中有一個Block,解題報告裏面把Block看做了是牆,但是如果判斷
        沒有出maze,那麼maze[i][j] == 1.回溯的時候maze[i][j] == 0
    3.關於輸入輸出
        這道題解題報告十分經典的一個原因,就是mazi[i][j] = 1(能夠通過)
        maze[i][j] = 0不能通過,這跟WY學長提到的memset不能設1
        (否則內存變成1111111111111111)思想是一樣的
    4.關於搜索
        這道題說冰壺丟出去就要一直碰到Block才停下,所以有一個
        while(maze[i][j])
            tmp.x++....
        在+完之後tmp.x--,然後判斷tmp.x + 1是否在範圍內,來判斷是否扔出了範圍
        這點很贊
    5.關於回溯
        這題作者把_min設置爲了11,最多也就是11層,判斷每個節點p > _min的時候就回溯!
        既保證了最優解,又保證了剪枝,這個思想非常贊啊
    思路大概就是,每次撞牆判斷是否在範圍內,如果在範圍內那就對應的牆爲1(可以通過),然後
    繼續搜索,每次搜索到了Goal就_min = min (_min,tmp.p);
    而且,這道題扔出去了就搜索其他方向的思路(用了四個while循環)和其他的搜索模板給出
    向量direct[4][2] = { {0,1},{0,-1},{1,0},{-1,0} };的思路不一樣
    太讚了,簡直是可以作爲一個新模板,一定要好好做
*/
using namespace std;
const int c0de4fun = 30;
int maze[c0de4fun][c0de4fun];
struct Node
{
    int x,y,p;
};
Node pb,pe; //point of Begin,point of End;
int _min;
int W,H,tmp;
void DFS(Node nod)
{
    Node tmp,tmp1;
    tmp = nod;
    if ( tmp.x == pe.x && tmp.y == pe.y )
    {
        if ( _min > tmp.p )
        {
            _min = tmp.p;
        }
        return;  ///找到更優解就回溯
    }
    if ( tmp.p + 1 > _min )
        return ; ///這個回溯剪枝是一個Punch Point!

    tmp1 = tmp;
    while(maze[tmp1.x][tmp1.y])
    {
        tmp1.x++;
        if( tmp1.x == pe.x && tmp1.y == pe.y)
        {
            if ( tmp1.p + 1 < _min)
            {
                _min = tmp1.p + 1;
            }
            return;
        }
    }
    tmp1.x--; ///撞牆了
    if ( tmp1.x + 1 <= H && tmp1.x != tmp.x)
    {   ///沒有越界
        ///發生過移動
        tmp1.p = tmp.p + 1;
        maze[tmp1.x+1][tmp1.y] = 1;
        DFS(tmp1);
        maze[tmp1.x+1][tmp1.y] = 0; //回溯
    }

    tmp1 = tmp;

    while(maze[tmp1.x][tmp1.y])
    {
        tmp1.y++;
        if( tmp1.x == pe.x && tmp1.y == pe.y)
        {
            if ( tmp1.p + 1 < _min)
            {
                _min = tmp1.p + 1;
            }
            return;
        }
    }
    tmp1.y--; ///撞牆了
    if ( tmp1.y + 1 <= W && tmp1.y != tmp.y)
    {   ///沒有越界
        ///發生過移動
        tmp1.p = tmp.p + 1;
        maze[tmp1.x][tmp1.y+1] = 1;
        DFS(tmp1);
        maze[tmp1.x][tmp1.y+1] = 0; //回溯
    }

    tmp1 = tmp;
    while(maze[tmp1.x][tmp1.y])
    {
        tmp1.x--;
        if( tmp1.x == pe.x && tmp1.y == pe.y)
        {
            if ( tmp1.p + 1 < _min)
            {
                _min = tmp1.p + 1;
            }
            return;
        }
    }
    tmp1.x++; ///撞牆了
    if ( tmp1.x - 1 > 0 && tmp1.x != tmp.x)
    {   ///沒有越界
        ///發生過移動
        tmp1.p = tmp.p + 1;
        maze[tmp1.x-1][tmp1.y] = 1;
        DFS(tmp1);
        maze[tmp1.x-1][tmp1.y] = 0; //回溯
    }

    tmp1 = tmp;
    while(maze[tmp1.x][tmp1.y])
    {
        tmp1.y--;
        if( tmp1.x == pe.x && tmp1.y == pe.y)
        {
            if ( tmp1.p + 1 < _min)
            {
                _min = tmp1.p + 1;
            }
            return;
        }
    }
    tmp1.y++; ///撞牆了
    if ( tmp1.y - 1 > 0 && tmp1.y != tmp.y)
    {   ///沒有越界
        ///發生過移動
        tmp1.p = tmp.p + 1;
        maze[tmp1.x][tmp1.y-1] = 1;
        DFS(tmp1);
        maze[tmp1.x][tmp1.y-1] = 0; //回溯
    }
}
int main()
{
#ifdef INPUT
    freopen("b:\\acm\\poj3009\\input.txt","r",stdin);
#endif
    while ( scanf("%d%d",&W,&H) != EOF && W != 0 && H != 0)
    {
        tmp = 0;
        memset(maze,0,sizeof(int)*c0de4fun*c0de4fun);
        _min = 11;
        for( int i = 1 ; i <= H ; i++)
        {
            for( int j = 1 ; j<= W; j++)
            {
                scanf("%d",&tmp);
                maze[i][j] = 1;
                if ( tmp == 1 )
                {
                    maze[i][j] = 0;
                }
                if ( tmp == 3 )
                {
                    pe.x = i;
                    pe.y = j;
                }
                if ( tmp == 2 )
                {
                    pb.x = i;
                    pb.y = j;
                    pb.p = 0;
                }
            }
        }
        DFS(pb);

        if( _min <= 10 )
        {
            printf("%d\n",_min);
        }
        else
        {
            printf("-1\n");
        }
    }
    return 0;
}

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