hdu1401

hud1401纸牌

题目描述:

Solitaire 是一种在 8x8 棋盘上玩的游戏。棋盘的行和列分别从1到8编号,分别从上到下和从左到右。

棋盘上有四个相同的棋子。在一次移动中,允许:

①将棋子移到空的相邻区域(向上、向下、向左或向右)

② 跳过相邻棋子到空的区域(向上、向下、向左或向右)

如图:

所以有四种走法:向上走一步;向右走一步,跳过右边相邻的;向下走一格,跳过下面那个;想左直接走一格。不过每个棋子只能走四步最多,题目的要求是给定你一个目标位置,和最初位置,在每个棋子只能最多走四步,且所有棋子不能走超过八步的要求下移动成目标位置,可以输出是的,不可以的输出否

 

 这道题采用双向的广搜算法,这道题的技巧还是很多的,最重要的是怎么对棋盘状态判重这个很重要,其次就是棋子有四个,开八维数组判重,但是四个棋子全排列有很多种坐标。这里就需要排序处理,按棋子坐标升序依次往八维数组里面放。其实也就是通过排序hash了,你也可以对四个棋子的全排列顺序进行标记。不过写的代码会很多。最好的标记就是按照棋子升序标记,这样就不会很麻烦。tbfs + sort排序,思路就是正向拓展四次,反向拓展四次,如果两个范围跑出来的圆圈能产生交点那么一定可以,如果tbfs跑出来的范围没有交点代表无法实现,这样就能避免内存消耗太大已经时间不理想的情况。
 

代码:


#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
struct point{                                                         //定义一个坐标结构体
    int x,y;
};
struct info{
    point a[4];                                            //定义一个结构体来记录数组
    int step;
}s,e;
bool map[10][10];
char v[8][8][8][8][8][8][8][8];                                //八位数组判重
int dx[] = {1,-1,0,0};
int dy[] = {0,0,-1,1};
queue<info>q[2];
void clear_set()                          //清空函数                            
{
    memset(v,false,sizeof(v));
    while(!q[0].empty()){
        q[0].pop();
    }
    while(!q[1].empty()){
        q[1].pop();
    }
    memset(v,0,sizeof(v));
}
bool cmp(point s1,point s2)                             //排序规则 ,先按纵坐标大小排序,再按横坐标排序。
{
    if(s1.x == s2.x){
        return s1.y < s2.y;         
    }
    else{
        return s1.x < s2.x;
    }
}
inline void set_map(info p)
{
    map[p.a[0].x][p.a[0].y] = true;
    map[p.a[1].x][p.a[1].y] = true;
    map[p.a[2].x][p.a[2].y] = true;
    map[p.a[3].x][p.a[3].y] = true;
}
inline void set_visited(info p,char x)            //设置标记 
{
    v[p.a[0].x][p.a[0].y][p.a[1].x][p.a[1].y][p.a[2].x][p.a[2].y][p.a[3].x][p.a[3].y] = x;
}
inline char get_visited(info p)                //获得标记值 
{
    return v[p.a[0].x][p.a[0].y][p.a[1].x][p.a[1].y][p.a[2].x][p.a[2].y][p.a[3].x][p.a[3].y];
}
inline bool check(int x,int y)                //边界检查 
{
    if(x >= 0 && x < 8 && y >=0 && y < 8){
        return true;
    }
    else{
        return false;
    }
}
int tbfs()                                                                                    //双搜函数
{
    set_visited(s,'1');
    set_visited(e,'2');
    s.step = 0;e.step = 0;
    q[0].push(s);q[1].push(e);
    info ptr,str;
    while(!q[0].empty() || !q[1].empty()){
        if(!q[0].empty()){
            ptr = q[0].front();q[0].pop();
            if(ptr.step >= 4){                                    //大于等于4步不再拓展 
                continue;
            }
            memset(map,false,sizeof(map));
            set_map(ptr);
            for(int i = 0;i < 4;i++){
                for(int j = 0;j < 4;j++){
                    info p;
                    memcpy(&p,&ptr,sizeof(info)); 
                    p.a[i].x = ptr.a[i].x + dx[j];
                    p.a[i].y = ptr.a[i].y + dy[j];
                    if(!check(p.a[i].x,p.a[i].y)){                //走出边界跳掉 
                        continue;
                    }
                    if(map[p.a[i].x][p.a[i].y]){                //相邻点不能走通,进行跳跃
                        p.a[i].x += dx[j];
                        p.a[i].y += dy[j];
                        if(!check(p.a[i].x,p.a[i].y)){            //跳跃之后检查边界 
                            continue;
                        }
                    }
                    sort(p.a,p.a+4,cmp);
                    if(get_visited(p) == '2'){
                        return 1;
                    }
                    else if(get_visited(p) == '1'){
                        continue;
                    }
                    p.step = ptr.step + 1;
                    set_visited(p,'1');
                    q[0].push(p);
                }
            }
        }
        if(!q[1].empty()){
            str = q[1].front();
            q[1].pop();
            if(str.step >= 4){
                continue;
            }
            memset(map,false,sizeof(map));
            set_map(str);
            for(int i = 0;i < 4;i++){
                for(int j = 0;j < 4;j++){
                    info p;
                    memcpy(&p,&str,sizeof(info)); 
                    p.a[i].x = str.a[i].x + dx[j];
                    p.a[i].y = str.a[i].y + dy[j];
                    if(!check(p.a[i].x,p.a[i].y)){
                        continue;
                    }
                    if(map[p.a[i].x][p.a[i].y]){
                        p.a[i].x += dx[j];
                        p.a[i].y += dy[j];
                        if(!check(p.a[i].x,p.a[i].y)){
                            continue;
                        }
                    }
                    sort(p.a,p.a+4,cmp);
                    if(get_visited(p) == '1'){
                        return 1;
                    }
                    else if(get_visited(p) == '2'){
                        continue;
                    }
                    set_visited(p,'2');
                    p.step = str.step + 1;
                    q[1].push(p);
                }
            }
        } 
    }
    return -1;                        
}
int main()
{
    int x,y;
    while(~scanf("%d%d",&x,&y)){
        clear_set();
        s.a[0].x = x-1;s.a[0].y = y-1;
        for(int i = 1;i < 4;i++){
            scanf("%d%d",&x,&y);
            s.a[i].x = x-1;s.a[i].y = y-1;
        }
        for(int i = 0;i < 4;i++){
            scanf("%d%d",&x,&y);
            e.a[i].x = x-1;e.a[i].y = y-1;
        }
        sort(s.a,s.a+4,cmp);
        sort(e.a,e.a+4,cmp);
        int ans = tbfs();
        if(ans == -1){
            puts("NO");
        }
        else{
            puts("YES");
        }
    } 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zjsru_Beginner/article/details/121318354