uva:704 - Colour Hash

题目:704 - Colour Hash



题目大意:有一个彩色的两个轮子的拼盘,每次转动都是同颜色的一起转动。转动有四种,左边的顺时针,右边顺时针,左边逆时针,右边逆时针。


解题思路:刚开始用单向bfs,结果忽略了数组太大了,要4^16大小的数组,编译器开不下,所以改用了双向的bfs(),先逆向的bfs()一次,遍历步数只要到8就可以。以后每组数据再从正向开始bfs(),如果在步数不大于八的时候在逆向bfs()的记录里找到相同的状况的拼盘,就可以找到路径。所以步数不大于八的都找不到就找不到。

要注意:逆向的bfs()动作也要保存相反,还有步数不大于八的,不能第一次找到8就出来,要找完所有步数为八的。


#include<stdio.h>
#include<string.h>
#include<string>
#include<map>
using namespace std;

const int N = 24;
const int M = 1000000;

int n, tmp;
char st1[M][N], st2[M][N];
const char init[] = "034305650121078709:90121";
map<string, int> vis1;
map<string, int> vis2;
int dis1[M], dis2[M], fa1[M], fa2[M], step[M];

void LC(char *st){
	
	int t1 = st[10];
	int t2 = st[11];
	int i;
	for(i = 9; i >= 0; i--)
		st[i + 2] = st[i];
	st[0] = t1;
	st[1] = t2;
	for(i = 9; i < 12; i++)
		st[i + 12] = st[i];
}

void RC(char *st){

	int t1 = st[12];
	int t2 = st[13];
	int i;
	for(i = 14; i < N; i++)
		st[i - 2] = st[i];
	st[22] = t1;
	st[23] = t2;
	for(i = 9; i < 12; i++)
		st[i] = st[i + 12];

}
void LCC(char *st){

	int t1 = st[0];
	int t2 = st[1];
	int i;
	for(i = 2; i < 12; i++)
		st[i - 2] = st[i];
	st[10] = t1;
	st[11] = t2;
	for(i = 9; i < 12; i++)
		st[i + 12] = st[i];
}

void RCC(char *st){

	int t1 = st[22];
	int t2 = st[23];
	int i;
	for(i = 21; i >= 12; i--)
		st[i + 2] = st[i];
	st[12] = t1;
	st[13] = t2;
	for(i = 9; i < 12; i++)
		st[i] = st[i + 12];
}

int bfs(){

	vis1.clear();
	int front = 0, rear = 1;
	memset(fa1, 0, sizeof(fa1));
	vis1[st1[0]] = 1;
	memset(step, 0, sizeof(step));
	if(vis2[st1[front]])
		return front;
	while(front < rear){
		
		if(step[front] >= 8){
			
			front++;
			continue;
		}
		for(int i = 0; i < 4; i++){
			
			step[rear] = step[front] + 1;
			memcpy(st1[rear], st1[front], sizeof(st1[front]));
			if(i == 0)
				LC(st1[rear]);
			else if(i == 1)
				RC(st1[rear]);
			else if(i == 2)
				LCC(st1[rear]);
			else
				RCC(st1[rear]);
			if(vis1[st1[rear]] == 0){
				
				vis1[st1[rear]] = 1;
				dis1[rear] = i + 1;
				fa1[rear] = front;
				if(vis2[st1[rear]] != 0)
					return rear;
				rear++;
			}

		}
		front++;
	}
	return -1;
}

void bfs_back(){

	int front = 0, rear = 1;
	memset(fa2, 0, sizeof(fa2));
	memcpy(st2[front], init, sizeof(init));
	memset(step, 0, sizeof(step));
	vis2[st2[0]] = 1;
	while(front < rear){
	
		if(step[front] >= 8){
			
			front++;
			continue ;
		}
		for(int i = 0; i < 4; i++){
			
			step[rear] = step[front] + 1;
			memcpy(st2[rear], st2[front], sizeof(st2[front]));
			if(i == 0)
				LC(st2[rear]);
			else if(i == 1)
				RC(st2[rear]);
			else if(i == 2)
				LCC(st2[rear]);
			else
				RCC(st2[rear]);
			if(vis2[st2[rear]] == 0){
				
				vis2[st2[rear]] = rear;
				switch(i + 1){

				case 1: dis2[rear] = 3;break;
				case 2: dis2[rear] = 4;break;
				case 3: dis2[rear] = 1;break;
				case 4: dis2[rear] = 2;
				}
				fa2[rear] = front;
				rear++;
			}

		}
		front++;
	}

}

void print_path(int rear){

	if(rear){

		print_path(fa1[rear]);
		printf("%d", dis1[rear]);
	}
}

void print_back(int rear){
	
	while(rear){

		printf("%d", dis2[rear]);
		rear = fa2[rear];
	}
}

int main(){

	scanf("%d", &n);
	bfs_back();
	while(n--){
	
		for(int i = 0; i < N; i++){

			scanf("%d", &tmp);
			st1[0][i] = tmp + '0';
		}
		if(memcmp(init, st1[0], sizeof(init)) == 0){

			printf("PUZZLE ALREADY SOLVED\n");
			continue;
		}
		int c = bfs();
		if(c == -1)
			printf("NO SOLUTION WAS FOUND IN 16 STEPS\n");
		else {
			
			print_path(c);
			print_back(vis2[st1[c]]);
			printf("\n");
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值