【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;
}

你可能感兴趣的:(c,struct,测试,input,include,fun)