Planning mobile robot on Tree (EASY Version) UVA - 12569 

https://blog.csdn.net/wcr1996/article/details/43631771

感谢这位博主,学了很多,代码相当优秀

很有难度的一道题

思路的确不难,就是bfs搜索,但是具体实现起来还是很花时间的,数据结构还是比较好表示的,但是直接用结构体来表示石头和机器人位置会会超时,所以需要用到状态压缩

代码在原来的基础上加了部分注释,方便回顾时理解

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<assert.h>
#include<vector>
#include<list>
#include<map>
#include<set>
#include<sstream>
#include<stack>
#include<queue>
#include<string>
#include<bitset>
#include<algorithm>
#pragma warning(disable:4996)
#define me(s)  memset(s,0,sizeof(s))
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
#define Max(a,b) (a)>(b)?(a):(b);
#define Min(a,b) (a)<(b)?(a):(b);
using namespace std;
typedef pair <int, int> pii;
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = { 0, -1, 0, 1, -1, -1, 1, 1 };
const int dc[] = { -1, 0, 1, 0, -1, 1, -1, 1 };
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const double eps = 1e-15;
const int maxn = 15;
const int maxstate = (1 << maxn)*maxn + 10;   //机器人和石头的位置状态总数是1<<maxn,注意这个是不区分机器人和石头的,所以还要考虑机器人位置
int n, m, s, t;
int g[maxn][maxn];
int fa[maxstate], dist[maxstate];
bool vis[maxstate][maxn];
typedef int state[2];
typedef int go[2];
state st[maxstate];
state k[maxstate];
void read()
{
	me(g); me(fa); me(dist); me(vis); me(st); me(k);
	scanf("%d%d%d%d", &n, &m, &s, &t);
	st[1][1] = s - 1; st[1][0] = 1 << (s - 1);   //st[1][1]存储了机器人的位置,也就是st[1][0]对应得二进制位
	_for(i, 0, m) {
		int k; scanf("%d", &k);
		st[1][0] |= 1 << (k - 1);             //存储石头位置
	}
	_for(i, 0, n - 1) {
		int u, v; scanf("%d%d", &u, &v);
		g[u - 1][v - 1] = g[v - 1][u - 1] = 1;//树转化为图
	}
}
int bfs()
{
	int front = 1, rear = 2;
	while (front < rear) {
		state &s = st[front];                 //提取队首节点
		if (s[1] == t - 1) return front;      //判断是否达到目标状态
		_for(i, 0, n) {
			if (!(s[0] & (1 << i))) continue;     //找到石头或者机器人
			_for(j, 0, n) {
				if ((s[0] & (1 << j)) || !g[i][j]) continue;  //找到一个可以石头和机器人可以转移的空位
				state &e = st[rear];                          //扩展状态
				memcpy(e, s, sizeof(s));
				if (i == s[1]) e[1] = j;                       //更新机器人位置
				e[0] ^= 1 << i | 1 << j;                         //交换位置 
				k[rear][0] = i + 1; k[rear][1] = j + 1;        //记录操作
				dist[rear] = dist[front] + 1; fa[rear] = front;  //更新步数,记录前驱方便打印
				if (!vis[e[0]][e[1]]) { rear++; vis[e[0]][e[1]] = true; }  //判重
			}
		}
		++front;
	}
	//全部搜索完依旧没有达到目标,说明无解
	return 0;
}
void print(int a) //递归打印
{
	if (!fa[a]) return;
	print(fa[a]);
	printf("%d %d\n", k[a][0], k[a][1]);
	return;
}
int main()
{
	int T, kcase = 0;
	scanf("%d", &T);
	while (T--) {
		read();
		int ans = bfs();
		printf("Case %d: %d\n", ++kcase, ans ? dist[ans] : -1);
		print(ans);
		printf("\n");
	}
		

	
}

猜你喜欢

转载自blog.csdn.net/qq_41776911/article/details/82691855