HDU - 1067 Gap 【BFS+字符串压缩状态】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1067

一开始看题目的时候,最苦恼的就是题目存在的状态数太多,空格可能存放的数字有28个,那么可能的状态就有 28!种,这个数目显然很大,所以不知道如何做。但事实上并不用都遍历一遍,虽然我知道,只要四个空格左边的数都是个位数为7的数,那么就可以肯定无解,这样能减少不少耗时,但是我没想到能减这么多。

所以用字符串压缩状态,并用map来记录遍历过的状态就行了。

#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int Maxn = 4e5+10;

struct Node {
    char stat[80];
    int step;
};

char Ed[80];

void bfs(char *ss) {
    map<string, int> vis;
    queue<Node> qu;
    Node tmp;
    memcpy(tmp.stat, ss, sizeof(tmp.stat));
    tmp.step = 0;
    qu.push(tmp);
    vis[ss] = 1;

    while (!qu.empty()) {
        tmp = qu.front(); qu.pop();
        if(!strcmp(tmp.stat, Ed)) {
            printf("%d\n", tmp.step); return;
        }
        int len = strlen(tmp.stat);

        for(int i = 0; i < len; i += 2) {
            if(tmp.stat[i] == '0' && (tmp.stat[i-1] != '7' || tmp.stat[i-1] != '0')) {
                Node now = tmp; now.step++;

                for(int j = 0; j < len; j += 2) {
                    if(now.stat[j] == tmp.stat[i-2] && now.stat[j+1] == tmp.stat[i-1]+1) {
                        now.stat[i] = now.stat[j]; now.stat[i+1] = now.stat[j+1];
                        now.stat[j] = now.stat[j+1] = '0';
                        if(!vis[now.stat]) {
                            vis[now.stat] = 1; qu.push(now);
                        }
                        break;
                    }
                }
            }
        }
    }
    printf("-1\n");
}

int main(void)
{
    int T;
    scanf("%d", &T);
    while (T--) {
        char str[80]; int tmp, p = 0;
        for(int i = 1; i <= 4; ++i) {
            str[p++] = '0'+i; str[p++] = '1';
            for(int j = 2; j <= 8; ++j) {
                scanf("%d", &tmp);
                if(tmp == 11 || tmp == 21 || tmp == 31 || tmp == 41) {
                    str[p++] = '0'; str[p++] = '0';
                } else {
                    str[p++] = '0'+(tmp/10);
                    str[p++] = '0'+(tmp%10);
                }
            }
        }
        str[p] = '\0';

        p = 0;
        for(int i = 1; i <= 4; ++i) {
            for(int j = 1; j <= 7; ++j) {
                Ed[p++] = i+'0'; Ed[p++] = j+'0';
            }
            Ed[p++] = '0'; Ed[p++] = '0';
        }
        Ed[p] = '\0';
        bfs(str);
    }
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值