HDU 1254 推箱子游戏(搞了一下午。。。)

中文题目:http://acm.hdu.edu.cn/showproblem.php?pid=1254
一开始常规的人用来做主导,想着想着不对劲,其实是箱子为主导,人只是箱子能否推进的一个判断。
可以使用两个BFS,人这里也可以DFS。看见别人有用四维标记的有用图中图的判重,我也用一下图中图好了。

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

int n, m;
int map[10][10];
int vec[4][2] = {{-1,0}, {0,1}, {1,0}, {0,-1}};
int visited[10][10][4];//标记箱子。有四个方向,所有一个点可以推四次
int visitedP[10][10];//标记人

struct node
{
	int x;
	int y;
	int step;
	int innerMap[10][10];//保存每个点修改的图
	bool check()
	{
		if(x>=0 && x<n && y>=0 && y<m)
			return true;
		return false;
	}
}boxStart, peopleStart, peopleEnd, target;

int PeopleBFS(node t)
{
    peopleStart = t;
	memset(visitedP, 0, sizeof(visitedP));

	queue<node> Q;
	//找人的位置
	for (int i = 0; i<n; i++)
	{
		for (int j = 0; j<m; j++)
		{
			if (t.innerMap[i][j] == 4)
			{
				peopleStart.x = i;
				peopleStart.y = j;
				peopleStart.step = 0;
			}
		}
	}
	if(peopleStart.x == peopleEnd.x && peopleStart.y == peopleEnd.y)
		return true;
	visitedP[peopleStart.x][peopleStart.y] = true;

	Q.push(peopleStart);
	while (!Q.empty())
	{
		node q = Q.front();
		Q.pop();
		for (int i = 0; i<4; i++)
		{
			node p = q;
			p.x += vec[i][0];
			p.y += vec[i][1];
			p.step++;
			if (p.check() && !visitedP[p.x][p.y] && t.innerMap[p.x][p.y]!=1
                        && t.innerMap[p.x][p.y]!= 2)//不是墙不是箱
			{
				visitedP[p.x][p.y] = true;
				if (p.x == peopleEnd.x && p.y == peopleEnd.y)//可以到
				{
					return true;
				}
				Q.push(p);
			}
		}
	}
	return false;
}


int BoxBFS()
{
	queue<node> Q;
	Q.push(boxStart);
	while (!Q.empty())
	{
	    node q = Q.front();
		Q.pop();
		for (int i = 0; i<4; i++)
		{
			node p = q;
			p.x += vec[i][0];
			p.y += vec[i][1];
			p.step++;
			if (p.check() && !visited[p.x][p.y][i] && map[p.x][p.y] != 1)
			{
				//找出人站在箱子前进方向的反方向
				peopleEnd = q;
				peopleEnd.x = q.x - vec[i][0];
				peopleEnd.y = q.y - vec[i][1];
				if (peopleEnd.check())//人可以站在这个位置
				{
					if (PeopleBFS(peopleEnd))//人可以到达					{
						swap(p.innerMap[p.x][p.y], p.innerMap[q.x][q.y]);//箱子走一步
						swap(p.innerMap[peopleEnd.x][peopleEnd.y],
                     p.innerMap[peopleStart.x][peopleStart.y]);//人跟上					
                            visited[p.x][p.y][i] = true;
						if (map[p.x][p.y] == 3)//到达目的地
						{
							return p.step;
						}
					    Q.push(p);

					}
				}
			}
		}
	}
	return -1;
}


int main()
{
	int T;
	cin>>T;
	while (T--)
	{
		cin>>n>>m;
		memset(visited, 0, sizeof(visited));
		for (int i = 0; i<n; i++)
		{
			for (int j = 0; j<m; j++)
			{
				cin>>map[i][j];
				boxStart.innerMap[i][j] = map[i][j];
				if (map[i][j] == 2)//箱子起始
				{
					boxStart.x = i;
					boxStart.y = j;
					boxStart.step = 0;
				}
			}
		}
		cout<<BoxBFS()<<endl;
	}
	return 0;
}


原文地址:https://www.cnblogs.com/riskyer/p/3275676.html