hdu1195 Open the Lock BFS 广搜

12 篇文章 0 订阅

题目链接:here

题意:

给你四个数字,每次可以将其中任何一个数字 +1 或者 -1 ; 1的时候-1 等于9  ;9的时候+1 等于1;  问最少需要变换几次,才可以变到目标序列。。

分析:

我先用广搜做了一遍,随后又用双向广搜做了一遍,发现双向广搜效率的确很高!

贴一下图:


第一个是双向广搜的,下面的是广搜。。。

晒代码:

广搜:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

struct node
{
	int num[4];
	int step;
};
queue<node> q;
bool vis[10][10][10][10];
int ansnum[4];
int ans;
int dir[8][4] = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1},{-1,0,0,0},{0,-1,0,0},{0,0,-1,0},{0,0,0,-1}};

void init()
{
	memset(vis, false, sizeof(vis));
	while (!q.empty()) q.pop();
}

bool istrue(node x)
{
	if (x.num[0] == ansnum[0] && x.num[1] == ansnum[1] && x.num[2] == ansnum[2] && x.num[3] == ansnum[3])
		return true;
	return false;
}

bool judge(node x)
{
	if (vis[x.num[0]][x.num[1]][x.num[2]][x.num[3]]) return false;
	return true;
}

node change(node a, int b)
{
	a.step ++;

	if (b < 4)		// +
	{
		if (a.num[b] == 9) a.num[b] = 1;
		else a.num[b] ++;
	}
	else if (b < 8)	// -
	{
		if (a.num[b%4] == 1) a.num[b%4] = 9;
		else a.num[b%4] = a.num[b%4] - 1;
	}
	else	// 换
	{
		int tmp;
		b %= 4;
		tmp = a.num[b];
		a.num[b] = a.num[b+1];
		a.num[b+1] = tmp;
	}

	return a;
}

void bfs()
{
	node now, next;
	while (!q.empty())
	{
		now = q.front();
		q.pop();

		if (istrue(now))
		{
			ans = now.step;
			return ;
		}

		for (int i = 0; i < 11; i++)
		{
			next = change(now, i);
			if (judge(next))
			{
				vis[next.num[0]][next.num[1]][next.num[2]][next.num[3]] = true;
				q.push(next);
			}
		}
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		init();
		int a, b;
		node now;
		scanf("%d %d", &a, &b);

		for (int i=3; i>=0; i--)
		{
			ansnum[i] = a  % 10;
			now.num[i] = b % 10;
			a /= 10;
			b /= 10;
		}
		now.step = 0;
		q.push(now);
		vis[now.num[0]][now.num[1]][now.num[2]][now.num[3]] = true;

		bfs();

		printf("%d\n", ans);
	}
	return 0;
}

双向广搜:

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

struct node
{
	int num[4];
	int step;
};
queue<node> q[2];
int vis[2][10][10][10][10];
int ansnum[4];
int ans;

void init()
{
	ans = -1;
	memset(vis, -1, sizeof(vis));
	while (!q[0].empty()) q[0].pop();
	while (!q[1].empty()) q[1].pop();
}

bool istrue(node x, int i)
{
	if (vis[1^i][x.num[0]][x.num[1]][x.num[2]][x.num[3]] != -1)
		return true;
	return false;
}

bool judge(node x, int i)
{
	if (vis[i][x.num[0]][x.num[1]][x.num[2]][x.num[3]] != -1) return false;
	return true;
}

node change(node a, int b)
{
	a.step ++;

	if (b < 4)		// +
	{
		if (a.num[b] == 9) a.num[b] = 1;
		else a.num[b] ++;
	}
	else if (b < 8)	// -
	{
		if (a.num[b%4] == 1) a.num[b%4] = 9;
		else a.num[b%4] = a.num[b%4] - 1;
	}
	else	// 换
	{
		int tmp;
		b %= 4;
		tmp = a.num[b];
		a.num[b] = a.num[b+1];
		a.num[b+1] = tmp;
	}

	return a;
}

void bfs(int j)
{
	node now, next;
	if (ans != -1 || q[j].empty()) return ;
	int first = q[j].front().step;
	while (!q[j].empty() && q[j].front().step == first)
	{
		now = q[j].front();
		q[j].pop();

		if (istrue(now, j))
		{
			ans = vis[j][now.num[0]][now.num[1]][now.num[2]][now.num[3]] + vis[1^j][now.num[0]][now.num[1]][now.num[2]][now.num[3]];
			return ;
		}

		for (int i = 0; i < 11; i++)
		{
			next = change(now, i);
			if (judge(next, j))
			{
				vis[j][next.num[0]][next.num[1]][next.num[2]][next.num[3]] = next.step;
				q[j].push(next);
			}
		}
	}
}

void db_bfs()
{
	while (ans == -1)
	{
		bfs(0);
		bfs(1);
	}
}

int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		init();
		int a, b;
		node now0, now1;
		scanf("%d %d", &a, &b);

		for (int i=3; i>=0; i--)
		{
			now0.num[i] = a % 10;
			now1.num[i] = b % 10;
			a /= 10;
			b /= 10;
		}
		now0.step = 0;
		q[0].push(now0);
		vis[0][now0.num[0]][now0.num[1]][now0.num[2]][now0.num[3]] = 0;
		now1.step = 0;
		q[1].push(now1);
		vis[1][now1.num[0]][now1.num[1]][now1.num[2]][now1.num[3]] = 0;

		db_bfs();

		printf("%d\n", ans);
	}
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值