C++
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <string>
#include <unordered_map>
#include <algorithm>
using namespace std;
string cur(32,1),target(32,1); //目标状态
struct Node{
string status;
int step;
Node(string s,int step):status(s),step(step){}
Node(){
}
};
void move(string &str,char ch,int pos){ //将ch放在pos位置上
int i;
for(i=0;i<32;i++)
if(str[i]==ch)
break;
if(i!=32){ //若找到了
str[pos] = ch;
str[i] = 1;
}
}
int bfs(){
unordered_map<string, bool> mp; //当前状态是否被访问过
Node now(cur,0),next;
queue<Node> q;
q.push(now);
mp[now.status] = true;
while(!q.empty()){
now = q.front();
q.pop();
if(now.status == target) //由于每步操作代价为1,所以不需要pq
return now.step;
for(int i=0;i<4;i++){
for(int j=1;j<8;j++){
if(now.status[i*8+j]==1 && now.status[i*8+j-1]!=1){
//找到一个可以移动的空位,将同suit中的后继放入该位置
next = now;
move(next.status,now.status[i*8+j-1]+1,i*8+j);
if(!mp[next.status]){ //若该状态还没有被访问过
mp[next.status] = true;
next.step++;
q.push(next);
}
}
}
}
}
return -1;
}
void read(){
int val;
for(int i=0;i<4;i++)
for(int j=1;j<8;j++){
scanf("%d",&val);
if(val%10==1){ //若是1开头的,则直接进行移动
int pos = (val/10-1)*8; //放在对应行首
cur[pos] = val;
cur[i*8+j] = 1;//当前位置为空
}
else{ //否则放到相应的位置上
cur[i*8+j] = val;
}
}
}
int main(){
int T;
for(int i=0;i<4;i++)
for(int j=0;j<7;j++)
target[i*8+j] = (i+1)*10 + (j+1); //设置为string可以直接比较两个状态
scanf("%d",&T);
while(T--){
read();
printf("%d\n",bfs());
}
return 0;
}
JAVA:
import java.util.*;
public class HDU1067_bfs {
public static String target;
public static class Node{
String status; //当前状态
int step; //已经使用的步数
Node(String status,int step){
this.status = new String(status);
this.step = step;
}
Node(){
this.step = 0;
}
Node(Node t){
this.status = new String(t.status);
this.step = t.step;
}
}
public static String change(String str,char ch,int pos) {
//将ch移动到pos上,pos是一个空位
int i=0;
for(i=0;i<32;i++)
if(str.charAt(i)==ch)
break;
char[] arr = str.toCharArray();
if(i!=32) { //若找到了该字符
arr[i] = 0;
arr[pos] = ch;
}
return String.valueOf(arr);
}
public static int bfs(char[] arr) {
HashMap<String,Boolean> vis = new HashMap<>();
String now = String.valueOf(arr); //初始状态
Queue<Node> q = new LinkedList<>();
Node cur,next;
cur = new Node();
cur.status = now; //将初始状态进行赋值
cur.step = 0;
vis.put(cur.status, true);
q.offer(cur);
while(!q.isEmpty()) {
cur = q.poll();
if(cur.status.equals(target))
return cur.step;
char[] a = cur.status.toCharArray();
for(int i=0;i<4;i++) {
for(int j=1;j<8;j++) { //寻找可以移动的位置
if(a[i*8+j]==0 && a[i*8+j-1]!=0) {
next = new Node(cur);
char ch = next.status.charAt(i*8+j-1);
int num = (int)(ch);
num++;
ch = (char)(num);
String str = change(next.status,ch,i*8+j);
next.status = str; //变换后的状态
if(!vis.containsKey(next.status)) {
vis.put(next.status, true);
next.step++;
q.offer(next);
}
}
}
}
}
return -1;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
char[] tar = new char[32];
for(int i=0;i<4;i++) {
for(int j=0;j<7;j++) {
int num = (i+1)*10+(j+1);
char ch = (char)(num);
tar[i*8+j] = ch;
}
}
target = String.valueOf(tar);
//target中,非0位置为具体的值,空位为int型的0
while(T-->0) {
char[] arr = new char[32]; //读入当前状态
int val ;
for(int i=0;i<4;i++) {
for(int j=1;j<8;j++) {
val = sc.nextInt();
char ch = (char)(val);
if(val%10==1) {
int pos = (val/10-1)*8;
arr[pos] = ch;
}
else {
arr[i*8+j] = ch;
}
}
}//读入数据
int res = bfs(arr);
System.out.println(res);
}
}
}