UVA 1533 - Moving Pegs 状态压缩 + bfs

本文介绍了一种解决特殊棋盘问题的算法实现,棋盘上每个位置可以为空或者放置一个球。球只能通过相邻且有球的位置跳跃,并且中间必须隔着一个空位。文章详细展示了如何使用广度优先搜索(BFS)来寻找从初始状态达到所有球都占据指定位置所需的最少步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题需要注意的是 当一个球的相邻位置为空时 不能直接跳过去 之间必须要有球垫着

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

#define bug puts("bug")

const int link[15][6] = { {-1,-1,-1,-1, 1, 2},  {-1, 0,-1, 2, 3, 4},  { 0,-1, 1,-1, 4, 5},  {-1, 1,-1, 4, 6, 7},
                                    { 1, 2, 3, 5, 7, 8},  { 2,-1, 4,-1, 8, 9},  {-1, 3,-1, 7,10,11},  { 3, 4, 6, 8,11,12},
                                    { 4, 5, 7, 9,12,13},  { 5,-1, 8,-1,13,14},  {-1, 6,-1,11,-1,-1},  { 6, 7,10,12,-1,-1},
                                    { 7, 8,11,13,-1,-1},  { 8, 9,12,14,-1,-1},  { 9,-1,13,-1,-1,-1} };

struct Node{
    int g;   // 0 represent empty and 1 represent full
    int step;
    int num;
    Node(int g = 0, int step = 0, int num = 0) : g(g), step(step), num(num){}
};

struct Path{
    int u, v;
    Path(int u = 0, int v = 0) : u(u), v(v){}
};

const int maxn = 16;

int n, cnt, k;
int fa[1 << maxn];
bool vis[1 << maxn];
Path path[1 << maxn];
Node S;

void print(int c){
    if(fa[c] == -1) return;
    print(fa[c]);
    if(c == k) printf("%d %d\n", path[c].u + 1, path[c].v + 1);
    else printf("%d %d ", path[c].u + 1, path[c].v + 1);
}

int bfs(){
    queue<Node> Q;
    Q.push(S);
    vis[Q.front().g] = true;
    while(!Q.empty()){
//            bug;
        Node cur = Q.front(); Q.pop();
        if(cur.g == (1 << n)){
            k = cur.num;
            return cur.step;
        }
        for(int i = 0; i < 15; i++)if((1 << i) & cur.g){ //if full

            for(int j = 0; j < 6; j++){
                int x = (1 << i);
                int st = 0;
                int go = link[i][j];
                while(go != -1){ // find empty
                    if(!((1 << go) & cur.g)){
                        if(!st) break;
                        Node tmp;
                        x ^= cur.g;
                        x |= (1 << go);
                        tmp.g = x;
                        tmp.step = cur.step+1;

                        if(!vis[x]){
                            vis[x] = true;
                            tmp.num = ++cnt;
                            fa[cnt] = cur.num;
                            path[cnt] = Path(i, go);
                            Q.push(tmp);

                        }
                        break;
                    }
                    x |= (1 << go); // save
                    go = link[go][j];
                    st++;
                }
            }
        }
    }
    return -1;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        memset(vis, false, sizeof(vis));
        n--;
        int g = 0;
        for(int i = 0; i < 15; i++){
            if(i != n)
                g |= (1 << i);
        }
        S.g = g;
        S.step = 0;
        S.num = cnt = 0;
        fa[0] = -1;
        int ans = bfs();

        if(ans == -1){
            printf("IMPOSSIBLE\n");
        }
        else{
           printf("%d\n", ans);
           print(k);
        }

    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值