hdu 3500 还是搜索

这道题目由于每走一步的时候毛毛球是可以变换的 换言之 主体不唯一 所以这里搜索的设计有变化

再就是几个回溯的过程要注意。,。  小心使得万年船

#include <iostream>
#include <cstdio>
using namespace std;
char map[10][10];
int num;
int flag;
int mmove;
int dir[4][2] = {{-1,0},{0,-1},{0,1},{1,0}}; //U、L、R、D
char tow[4] = {'U','L','R','D'};

struct node
{
    int x,y;
    int direction;
}path[15];

int is_in(int x, int y) //判断是否在游戏界面中
{
    if(x >= 0 && x <= 6 && y >= 0 && y <= 7)
        return 1;
    else
        return 0;
}

void dfs(int cur)
{
    if(cur == num)
    {
    //走了num-1步之后直接返回
    /*
      没成功走一次,都会把一个毛毛球推出游戏界面,所以最多只可能走num-1步
    */
        flag = 1; //已经走完了相应的步数
        return;
    }

    for(int i=0; i<=6; i++)
    {
        for(int j=0; j<=7; j++)
        {
            if(map[i][j] == 'O') //按顺序进行搜索,如果搜索到了一个毛毛球,就看它是否能够移动
            {
                mmove = 0;
                for(int d=0; d<4; d++)
                {
                    int nx = i + dir[d][0];
                    int ny = j + dir[d][1];
                    if(is_in(nx, ny) && map[nx][ny] == 'O') //前方有毛毛球阻碍无法移动,直接continue选取下一个方向
                        continue;

                    /*
                    while循环这部分处理是关键,这里主要要处理好手拨动的毛毛球遇到另外一个球时要处理的状况,以及
                    撞击力量的传递处理。
                    */
                    while(is_in(nx, ny))
                    {
                        nx += dir[d][0];
                        ny += dir[d][1];

                         /*    遇到毛毛球k,其前面那个必然要为'O',而这个毛毛球k必须变为'X'。
                             通过while循环就可以处理好遇到毛毛球的情况,并且处理好撞击传递
                            的情况,例如第二组数据的撞击传递,所以这里设计的还是很巧妙的。
                          */

                        if(map[nx][ny] == 'O')
                        {
                            mmove = 1; //手拨动的毛毛球map[i][j]是可以移动的
                            map[nx][ny] = 'X';
                            map[nx - dir[d][0]][ny - dir[d][1]] = 'O';
                        }
                    }

                    if(mmove) //可以移动,进行记录
                    {
                        map[i][j] = 'X'; //移动之后原来的位置当然要置为'X'
                        path[cur].x = i;
                        path[cur].y = j;
                        path[cur].direction = d;


                        dfs(cur + 1);
                        //回溯之后
                        if(flag == 1)  //已经走完了就应该直接返回
                             return;

                                  //反方向走
                        nx -= dir[d][0];
                        ny -= dir[d][1];
                        while(nx != i || ny != j) //一直会推到手拨动球的起点map[i][j]
                        {
                            if(map[nx][ny] == 'O')  /*这说明是前面的球移动到此处的一个位置,
                                                     所以该位置还原成'X',而它后面的那个位置应该
                                                     还原成'O'
                                                     */
                            {
                                map[nx][ny] = 'X';
                                map[nx + dir[d][0]][ny + dir[d][1]] = 'O';
                            }
                            nx -= dir[d][0];
                            ny -= dir[d][1];

                        }
                        map[i][j] = 'O'; //起点还原

                    }

                }

            }
        }
    }
}



int main()
{
    int kase = 1;
    while(scanf("%s",map[0]) != EOF)
    {
        num = flag = 0;
        for(int i=1; i<=6; i++)
        {
            scanf("%s",map[i]);
        }

        for(int i=0; i<=6; i++)
        {
            for(int j=0; j<=7; j++)
            {
                if(map[i][j] == 'O')
                {
                    num++; //记录毛毛球的个数
                }
            }
        }

        dfs(1);
        if(kase != 1)
            cout<<endl;
        cout<<"CASE #"<<kase++<<":"<<endl;
        for(int i = 1; i<=num-1; i++)
        {
            cout<<path[i].x<<" "<<path[i].y<<" "<<tow[path[i].direction]<<endl;
        }
    }
    return 0;
}
posted @ 2016-10-11 20:33  猪突猛进!!!  阅读(352)  评论(0编辑  收藏  举报