算法笔记 问题 C: 【宽搜入门】8数码难题 终于AC啦

题目链接:http://codeup.cn/problem.php?cid=100000609&pid=2

吐槽

这次就是因为太粗心!


思路
  • 找最优步骤——BFS
  • 关键是确定每个入队的状态
  • 可用一个string记录每个状态
  • 0的位置从1开始
代码一(内存超限)已解决
//内存超限
#include<iostream>
#include<queue>
#include<map>
using namespace std;


string source = " ";
string target = " ";

struct Node
{
	string s;
	int x0;
	int step;
};

queue<Node> q;
map<string, bool> mp;

bool judge(Node top, int way)
{
	int index = top.x0;
	// cannot to up  1     123
	if (index <= 3 && index >= 1 && way == 1)
		return false;
	// cannot to down  2   789
	if (index <= 9 && index >= 7 && way == 2)
		return false;
	// cannot to left  3  147
	if (index % 3 == 1 && way == 3)
		return false;
	// cannot to right  4  369
	if (index % 3 == 0 && way == 4)
		return false;
	return true;
}

Node doSomething(Node top, int way)
{
	Node newNode = top;
	string s1 = top.s;
	int index = top.x0;
	switch (way)
	{
	case 1:
		swap(s1[index], s1[index - 3]);
		index -= 3;
		break;
	case 2:
		swap(s1[index], s1[index + 3]);
		index += 3;
		break;
	case 3:
		swap(s1[index], s1[index - 1]);
		index--;
		break;
	case 4:
		swap(s1[index], s1[index + 1]);
		index++;
		break;
	}

	newNode.s = s1;
	newNode.step++;
	newNode.x0 = index;
	
	return newNode;

}


int BFS(Node st)
{
	while (!q.empty())
	{
		q.pop();
	}

	q.push(st);
	mp[st.s] = true;
	while (!q.empty())
	{
		Node top = q.front();
		q.pop();
		if (top.s == target)
		{
			return top.step;
		}

		for (int way = 1; way <= 4; way++)
		{
			if (judge(top, way))
			{
				Node newNode = doSomething(top, way);
				if (mp[newNode.s] == false)
				{
					q.push(newNode);
					mp[newNode.s] = true;  // 就是这一行漏掉了!!!
				}		
			}
		}

	}
	return -1;
}


int main()
{
	int tmp[10] = { 0 };
	int index0 = 0;
	for (int i = 1; i <= 9; i++)
	{
		scanf("%d", &tmp[i]);
		source += tmp[i]+'0';
		if (tmp[i] == 0)
			index0 = i;
	}
	for (int i = 1; i <= 9; i++)
	{
		scanf("%d", &tmp[i]);
		target += tmp[i]+'0';
	}

	Node st = { source,index0,1 };
	printf("%d", BFS(st));

	return 0;
}

还不太清楚怎么解决超内存的问题,也许原因出在太多string?

解决!mp[newNode.s] = true; // 就是这一行漏掉了!!!

代码二 第一次修改 (还是内存超限)已解决
  • 把容器string全换成int类型
//内存超限
#include<iostream>
#include<queue>
#include<unordered_map>
using namespace std;


int source = 0;
int target = 0;

struct Node
{
	int s;
	int x0;
	int step;
};

queue<Node> q;
unordered_map<int, bool> mp;

bool judge(Node top, int way)
{
	int index = top.x0;
	// cannot to up  1     123
	if (index <= 3 && index >= 1 && way == 1)
		return false;
	// cannot to down  2   789
	if (index <= 9 && index >= 7 && way == 2)
		return false;
	// cannot to left  3  147
	if (index % 3 == 1 && way == 3)
		return false;
	// cannot to right  4  369
	if (index % 3 == 0 && way == 4)
		return false;
	return true;
}


int exchange(int num,int index1, int index2)
{
	// 整数是整数,不会影响0的index
	//int flag = num / 1e8;  // 012345678  结果就是0
	//char a[10] = { '0' };
	//if (flag != 0) // 123456780
	//{
	//	int p = 1e8;
	//	int temp = num;
	//	for (int i = 1; i <= 9; i++)
	//	{
	//		a[i] = temp / p + '0';
	//		temp = temp % p;
	//		p /= 10;
	//	}
	//}
	//else
	//{
	//	int p = 1e7;
	//	int temp = num;
	//	for (int i = 2; i <= 9; i++)
	//	{
	//		a[i] = temp / p + '0';
	//		temp = temp % p;
	//		p /= 10;
	//	}
	//}
	//swap(a[index1], a[index2]);

	//int sum = atoi(a);
	//return sum;

	int num2 = num;
	char cur[10];
	sprintf(cur, "%09d", num2);
	swap(cur[index1 - 1], cur[index2 - 1]);
	sscanf(cur, "%d", &num2);
	return num2;

}



Node doSomething(Node top, int way)
{
	Node newNode = top;
	int s1 = top.s;
	int index = top.x0;
	switch (way)
	{
	case 1:
		s1 = exchange(s1, index, index - 3);
		index -= 3;
		break;
	case 2:
		s1 = exchange(s1, index, index + 3);
		index += 3;
		break;
	case 3:
		s1 = exchange(s1, index, index - 1);
		index--;
		break;
	case 4:
		s1 = exchange(s1, index, index + 1);
		index++;
		break;
	}

	newNode.s = s1;
	newNode.step++;
	newNode.x0 = index;

	return newNode;

}


int BFS(Node st)
{
	while (!q.empty())
	{
		q.pop();
	}

	q.push(st);
	mp[st.s] = true;
	while (!q.empty())
	{
		Node top = q.front();
		q.pop();
		if (top.s == target)
		{
			return top.step;
		}

		for (int way = 1; way <= 4; way++)
		{
			if (judge(top, way))
			{
				Node newNode = doSomething(top, way);
				if (mp[newNode.s] == false)
				{
				    q.push(newNode);
				    mp[newNode.s] =true;  // 就是这一行!!!
				}
			}
		}

	}
	return -1;
}


int main()
{
	int tmp[10] = { 0 };
	int index0 = 0;
	for (int i = 1; i <= 9; i++)
	{
		scanf("%d", &tmp[i]);
		source = source*10 + tmp[i];
		if (tmp[i] == 0)
			index0 = i;
	}
	for (int i = 1; i <= 9; i++)
	{
		scanf("%d", &tmp[i]);
		target = target * 10 + tmp[i];
	}

	Node st = { source,index0,1 };
	printf("%d", BFS(st));

	return 0;
}
代码三 第二次修改(终于AC)
  • 采用数组模拟队列,代码略微修改了一番
  • 兜兜转转学习了新的点sscanf和sprintf
#include<iostream>
#include<queue>
#include<unordered_map>
using namespace std;


int source = 0;
int target = 0;
const int maxn = 400000;
struct Node
{
	int s;
	int x0;
	int step;
}q[maxn];

//queue<Node> q;

unordered_map<int, bool> mp;

bool judge(Node top, int way)
{
	int index = top.x0;
	// cannot to up  1     123
	if (index <= 3 && index >= 1 && way == 1)
		return false;
	// cannot to down  2   789
	if (index <= 9 && index >= 7 && way == 2)
		return false;
	// cannot to left  3  147
	if (index % 3 == 1 && way == 3)
		return false;
	// cannot to right  4  369
	if (index % 3 == 0 && way == 4)
		return false;
	return true;
}


int exchange(int num, int index1, int index2)
{
	// 整数是整数,不会影响0的index
	//int flag = num / 1e8;  // 012345678  结果就是0
	//char a[10] = { '0' };
	//if (flag != 0) // 123456780
	//{
	//	int p = 1e8;
	//	int temp = num;
	//	for (int i = 1; i <= 9; i++)
	//	{
	//		a[i] = temp / p + '0';
	//		temp = temp % p;
	//		p /= 10;
	//	}
	//}
	//else
	//{
	//	int p = 1e7;
	//	int temp = num;
	//	for (int i = 2; i <= 9; i++)
	//	{
	//		a[i] = temp / p + '0';
	//		temp = temp % p;
	//		p /= 10;
	//	}
	//}
	//swap(a[index1], a[index2]);

	//int sum = atoi(a);
	//return sum;

	int num2 = num;
	char cur[10];
	sprintf_s(cur, "%09d", num2);
	swap(cur[index1 - 1], cur[index2 - 1]);
	sscanf_s(cur, "%d", &num2);
	return num2;

}



Node doSomething(Node top, int way)
{
	Node newNode = top;
	int s1 = top.s;
	int index = top.x0;
	switch (way)
	{
	case 1:
		s1 = exchange(s1, index, index - 3);
		index -= 3;
		break;
	case 2:
		s1 = exchange(s1, index, index + 3);
		index += 3;
		break;
	case 3:
		s1 = exchange(s1, index, index - 1);
		index--;
		break;
	case 4:
		s1 = exchange(s1, index, index + 1);
		index++;
		break;
	}

	newNode.s = s1;
	newNode.step++;
	newNode.x0 = index;

	return newNode;

}

int head = 0, tail = 1;
int BFS(Node st)
{
	memset(q, 0, sizeof(q));
	q[head] = st;
	mp[st.s] = true;
	while (head!=tail)
	{
		Node top = q[head];
		if (top.s == target)
		{
			return top.step;  // 开始就是1了
		}

		for (int way = 1; way <= 4; way++)
		{
			if (judge(top, way))
			{
				Node newNode = doSomething(top, way);
				if (mp[newNode.s] == false)
				{
					mp[newNode.s] = true;
					q[tail++] = newNode;
				}
					
			}
		}
		head++;

	}
	return -1;
}


int main()
{
	int tmp[10] = { 0 };
	int index0 = 0;
	for (int i = 1; i <= 9; i++)
	{
		scanf_s("%d", &tmp[i]);
		source = source * 10 + tmp[i];
		if (tmp[i] == 0)
			index0 = i;
	}
	for (int i = 1; i <= 9; i++)
	{
		scanf_s("%d", &tmp[i]);
		target = target * 10 + tmp[i];
	}

	Node st = { source,index0,1 };
	printf("%d", BFS(st));

	return 0;
}
大神代码

参考
https://blog.csdn.net/u012283461/article/details/79078653

  • 注意点:同一层使用的是同一个cur
  • swap(cur, pos, swapTo);//一个新状态处理完了一定要记得将交换的0交换回来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值