AOJ 0121: Seven Puzzle【BFS】

From: AOJ 0121

思路:与前几题的bfs不同,这次的bfs没有明确的移动对象,看似任意一个数都可以当成对象移动。这时我们只需要抓住一个格子就行,比如我们把0作为移动对象,那么0在地图中漫游所有的格子得到的肯定就是问题的解空间。由于题目的输入是多个case,如果对每个case都运行一遍bfs就会TLE。这时我们祭出dp技能,只需要一次bfs就将解空间算出来,以后每个case只要到解空间中去找就行了。

#include <iostream>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
 
map<string, int> dp;
int direction[4] = { 1, -1, 4, -4 };
 
//************************************
// Method:    bfs
// FullName:  bfs
// Access:    public 
// Returns:   void
// Qualifier: 让0漫游整个字串
//************************************
void bfs()
{
	queue<string> que;
	que.push("01234567");
	dp["01234567"] = 0;
	while (!que.empty())
	{
		string now = que.front(); que.pop();
		// p是'0'的位置
		int p = 0;
		for (int j = 0; j < 8; ++j)
		{
			if (now[j] == '0')
			{
				p = j;
				break;
			}
		}
 
		for (int i = 0; i < 4; ++i)
		{
			int n = p + direction[i];
			if (0 <= n && n < 8 && 
				!(p == 3 && i == 0) && // 右上角不能再往右了
				!(p == 4 && i == 1))   // 左下角不能再往左了
			{
				string next = now;
				swap(next[p], next[n]);
				if (dp.find(next) == dp.end())
				{
					dp[next] = dp[now] + 1;
					que.push(next);
				}
			}
		}
	}
}
 

int main()
{
 
	bfs();
	string line;
	while (getline(cin, line))
	{
		line.erase(remove(line.begin(), line.end(), ' '), line.end());
		cout << dp[line] << endl;
	}
 
	return 0;
}

P.S. remove的用法与unique很接近,不能直接删除元素必须与erase结合使用

posted @ 2016-12-12 20:12  demianzhang  阅读(399)  评论(0编辑  收藏  举报