Sicily1150 简单魔板

解题大意:

其初始状态是

1 2 3 4

8 7 6 5

对魔板可进行三种基本操作:

A操作(上下行互换):

8 7 6 5

1 2 3 4

B操作(每次以行循环右移一个):

4 1 2 3

5 8 7 6

C操作(中间四小块顺时针转一格):

1 7 2 4

8 6 3 5

用上述三种基本操作,可将任一种状态装换成另一种状态。

Input

输入包括多个要求解的魔板,每个魔板用三行描述。

第一行步数N(不超过10的整数),表示最多容许的步数。

第二、第三行表示目标状态,按照魔板的形状,颜色用1到8的表示。

N 等于 -1 的时候,表示输入结束。

Output

对于每一个要求解的魔板,输出一行。

首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是A、B或C),相邻两个操作之间没有任何空格。

注意:如果不能达到,则 M 输出 -1 即可。

——————————————————————————————————————————————————

解题思路:因为N不大于10,所以可以用简单的DFS或BFS。这里采用DFS

数据结构:

  1. struct node{int x, int y, char op} 记录上下两排的数字表示状态,op表示操作(A,B,C)
  2. vector<Node> path;  记录每次遍历的操作顺序
    vector<char> result;  记录最终以最小步数到达目标状态的操作顺序
注意:
  1. 因为在回溯的时候节点的状态也需要恢复操作的前一状态,所以不能只记录操作的顺序,同时要记录节点的状态,所以节点状态和操作数作为一个数据结构记录起来。
  2. 由于此题要求最小步数到达,所有在深度遍历的时候先找到最小的,先记录起来。遍历完成后再打印。其他某些情况下,找到后就可以打印,其后的不需要遍历。
代码如下:
#include<iostream>
#include<vector>
using namespace std;

struct Node{
	int x;
	int y;
	char op;
	Node(int a, int b, char op){
		x=a; y=b; op=op;
	}
};

Node node(1234,8765,'0');
Node target(0,0,'0');
int flag=0;
int steps=0;
int minStep = 11;
vector<Node> path;
vector<char> result;

Node doA(Node node)
{
	return Node(node.y, node.x,'0');
}

Node doB(Node node)
{
	return Node((node.x%10)*1000+node.x/10, (node.y%10)*1000+node.y/10,'0');
}

Node doC(Node node)
{
	int i,j,a,b,i1,j1,c,d;
	i = (node.x / 1000)*1000;    //x千位
	j = node.x - i;     
	a = j / 100;      //x百位
	b = (j - a * 100) / 10;  //x十位
	i1 = (node.y / 1000) * 1000; //y千位
	j1 = node.y - i1;
	c = j1 / 100; //y百位
	d = (j1 - c*100) / 10; //y十位
	return Node(i+c*100+a*10+node.x%10, i1+d*100+b*10+node.y%10,'0');
}

void dfs(Node node, int n)
{
	int i;

	/*for(i=1;i<path.size();i++)
		cout << path[i].op << " ";
	cout << endl;
	cout << node.x << endl << node.y << endl << endl;
	system("pause");*/
//	if(flag == 1)
//		return;
	if(node.x == target.x && node.y == target.y && steps < minStep){
//		flag = 1;
		minStep = steps;
		result.clear();
		for(i=1; i<path.size(); i++)
			result.push_back(path[i].op);
			//cout << path[i].op;
		//cout << endl;
		return;
	}
	else if(steps >= n)
		return;
	else{
		for(i=0; i<3; i++){
			if(i==0){
				steps++;
				node.op = 'A';
				path.push_back(node);
				dfs(doA(node), n);
				steps--;
				path.pop_back();
			}
			else if(i == 1){
				steps++;
				node.op = 'B';
				path.push_back(node);
				dfs(doB(node), n);
				steps--;
				path.pop_back();
			}
			else{
				steps++;
				node.op='C';
				path.push_back(node);
				dfs(doC(node), n);
				steps--;
				path.pop_back();
			}
		}
	}

}

int arrToNum(int a, int b, int c, int d)
{
	return a*1000 + b*100 + c*10 + d;
}

int main()
{
	int n,a,b,c,d,i;

	while(cin>>n && n!= -1){
		cin >> a >> b >> c >> d;
		target.x = arrToNum(a,b,c,d);
		cin >> a >> b >> c >> d;
		target.y = arrToNum(a,b,c,d);
		node.x = 1234;
		node.y = 8765;
		flag = 0;
		steps = 0;
		minStep = 11;
		path.clear();
		result.clear();

		if(node.x == target.x && node.y == target.y)
			cout << 0 << endl;
		else{
			path.push_back(node);
			dfs(node, n);
		}

		if(minStep ==11)
			cout << -1 << endl;
		else{
			cout << minStep << " ";
			for(i=0; i<result.size(); i++)
				cout << result[i];
			cout << endl;
		}
	}

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值