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

有一定难度的一道题目,利用移位操作来对每一个节点的状态进行记录,如果该节点所在的那位为1,说明该节点中是存在机器人/障碍物的,如果为0,则表示没有,同时为了操作的统一性,我们的节点从0开始编号,也就是说,对于输入中的每个节点的编号都要减一。然后利用队列来模拟bfs搜索。定义一个新的数据结构node,node中的state用来记录现在的树中的节点的状态(需要移位操作计算出结果),同时length记录的是移动的操作次数,pre是后面用来递归打印操作的路径所用的,也就是记录的是前一个点的下标。pos用来记录当前的机器人所在的节点的位置。首先队列中放入初始的点,也就是机器人的位置pos在s中,同时pre为-1,length为0,state为初始计算出来的start。然后每次判断如果队列不为空,那么取出队列头的节点,首先判断机器人是否已经到了目标的位置,如果到达,那么记录最终状态对应的节点,结束循环,如果没有到达,那么继续后续操作。依次判断每一个节点在当前的状态下是否存在障碍物或者是机器人,如果存在,那么遍历和当前节点相邻的节点,如果相邻的节点是没有障碍物的(包括机器人在内),那么就将当前已经存在的某个节点中的障碍物转移道现在的空闲的节点中,这里要注意一个问题,如果转移的是机器人,那么需要更新机器人的位置的信息。然后判断目前的状态之前是否监测过,如果没有监测过,那么将当前的节点放置到队列当中,继续后面的循环操作即可,最后判断,必要的时候递归打印就行了,具体实现见如下代码:

#include<iostream>
#include<vector>
#include<string>
#include<set>
#include<stack>
#include<queue>
#include<map>
#include<algorithm>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<sstream>
#include<cstdio>
#include<deque>
#include<functional>
using namespace std;

const int maxn = 1 << 20;

class node{
public:
	int state,pos,pre,length;
	void set(int _state,int _pos,int _pre,int _length){
		state = _state, pos = _pos, pre = _pre, length = _length;
	}
};

node q[maxn];
vector<int> G[20];
int visit[20][maxn];

int T, n, m, s, t;

void getRes(int ind){
	if (q[ind].pre != 0) getRes(q[ind].pre);
	int from_s = q[q[ind].pre].state;
	int to_s = q[ind].state;
	int a, b;
	a = from_s ^ (from_s&to_s);
	b = to_s ^ (from_s&to_s);
	int u, k;
	for (int i = 0; i < n; i++){
		if ((1 << i)&a) u = i;
		if ((1 << i)&b) k = i;
	}
	cout << u+1 << " " << k+1 << endl;
}

int main(){
	cin >> T;
	memset(visit, 0, sizeof(visit));
	for (int i = 1; i <= T; i++){
		cin >> n >> m >> s >> t;
		for (int j = 0; j < n; j++) G[j].clear();
		s--, t--;
		int start = 0;
		for (int j = 0; j < m; j++){
			int t2;
			cin >> t2;
			t2--;
			start = start | (1 << t2);
		}
		for (int j = 0; j < n - 1; j++){
			int a, b;
			cin >> a >> b;
			a--, b--;
			G[a].push_back(b);
			G[b].push_back(a);
		}
		start |= (1 << s);
		int front = 0, rear = 1;
		q[front].set(start, s, -1,0);
		visit[s][start] = i;
		node ok;
		ok.set(0, 0, -1, -1);
		while (front < rear){
			node temp = q[front];
			if (temp.pos == t){
				ok = temp;
				break;
			}
			for (int ind = 0; ind < n; ind++){
				if ((1 << ind) & temp.state){
					for (int ind2 = 0; ind2 < G[ind].size(); ind2++){
						int ind3 = G[ind][ind2];
						if ((1 << ind3) & temp.state) continue;
						int pos = temp.pos, state2 = ((temp.state | (1 << ind3)) ^ (1 << ind));
						if (pos == ind) pos = ind3;
						if (visit[pos][state2]!= i){
							visit[pos][state2] = i;
							q[rear++].set(state2, pos, front, temp.length + 1);
						}
					}
				}
			}
			front++;
		}
		cout << "Case " << i << ": ";
		if (ok.length == -1){
			cout << "-1\n";
		}
		else{
			cout << ok.length << endl;
			getRes(front);
		}
		cout << endl;
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值