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

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

吐槽

这次就是因为太粗心!


文章目录

        • 吐槽
        • 思路
        • 代码一(内存超限)已解决
        • 代码二 第一次修改 (还是内存超限)已解决
        • 代码三 第二次修改(终于AC)
        • 大神代码

思路

  • 找最优步骤——BFS
  • 关键是确定每个入队的状态
  • 可用一个string记录每个状态
  • 0的位置从1开始

代码一(内存超限)已解决

//内存超限
#include
#include
#include
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
#include
#include
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
#include
#include
using namespace std;


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

//queue 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交换回来

你可能感兴趣的:(算法学习,bfs,算法,bfs)