UVa 12569 Planning mobile robot on Tree

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=842&problem=4014&mosmsg=Submission+received+with+ID+15350118


#include <cstdio>
#include <set>
#include <vector>
#include <queue>
#include <cstdlib>
#include <cstring>
using namespace std;
// next[i]代表与i相连的点
vector<int> next[20];

// 代表起点和终点
int s, t;
// 代表点的数目
int n;
// 代表障碍物数目
int m;

// 记录状态的结构体
typedef struct s_node
{
//	int place[20];	// place[0]为机器人位置,place[1...]为障碍物位置
//	int not_free[20];	// not_free[i] = 1代表i节点有东西占据
	int not_free_int;	// 哪些位为1代表哪些位被占用
	int r_place;		// 代表robot位置
//	int path[1000]; // 路径
	int from, to;
	int path_length;
	struct s_node* parent;		
}s_node;

// 记录所有的状态(robot和障碍物的位置)
set<pair<int,int> > state_set;

// 广度优先搜索所用的队列
queue<s_node*> my_queue;

int visit[40000][16];

s_node* root;

int main()
{
	int num;
	scanf("%d", &num);
	int count = 0;
	while(count < num)
	{
		for(int i = 0; i < 20; i++)
			next[i] = vector<int>();
//		state_set = set<vector<int> >();
		my_queue = queue<s_node*>();
		memset(visit, 0, sizeof(visit));
		scanf("%d %d %d %d", &n, &m, &s, &t);
		// 记录robot和障碍物的初始位置
/*		vector<int> array;
		array.push_back(s);
*/		
		
		// 读取障碍物的位置		
		int not_free[20];
		memset(not_free, 0, sizeof(not_free));
		not_free[s] = 1;
		for(int i = 1; i <= m; i++)
		{
			int x;
			scanf("%d", &x);
//			array.push_back(x);
			not_free[x] = 1;
		}

		// 记录边
		for(int i = 1; i <= n-1; i++)
		{
			int x, y;
			scanf("%d%d", &x, &y);
			next[x].push_back(y);
			next[y].push_back(x);	
		}	
	
		// 将初始节点加入队列
		s_node* p = (s_node*)malloc(sizeof(s_node));
		p->not_free_int = 0;
		p->r_place = s;
/*		memset(p->not_free, 0, sizeof(p->not_free));
		for(int i = 0; i < array.size(); i++)
		{
			p->place[i] = array[i];
			p->not_free[p->place[i]] = 1;
		}
		int not_free_int = 0;
*/		for(int i = 1; i <= n; i++)	
			p->not_free_int = p->not_free_int*2 + not_free[i];
		p->path_length = 0;
		p->parent = NULL;
		my_queue.push(p);
		visit[p->not_free_int][p->r_place] = 1;
//		state_set.insert(array);
//		state_set.insert

		root = p;
		// 广度优先搜索
		while(my_queue.size() > 0)
		{
			s_node* p = my_queue.front();
			my_queue.pop();
		/*	
			printf("path: ")
			for(int i = 0; i < path_length-1; i = i+2)
				printf("(%d,%d) ", p->path[i], p->path[i+1]);
			printf("\n");
			printf("not free: ")
			for(int i = 0; i < n; i++)
			{
				if(p->not_free[i] == 1)
					printf("%d ", i)
			}
	*/
			// 检查机器人是否到终点
			if(p->r_place == t)
			{
				printf("Case %d: %d\n", count+1, p->path_length);
				/*
				for(int i = 0; i <= p->path_length-2; i = i+2)
					printf("%d %d\n", p->path[i], p->path[i+1]);*/				
				if(p != root)
				{
					int path[1000];
					int p_count = 0;
					s_node* begin = p;
					while(begin != root)
					{
						path[p_count] = begin->from;
						path[p_count+1] = begin->to;
						p_count = p_count+2;
						begin = begin->parent;
					}
					for(int i = p_count-2; i >= 0; i= i-2)
					{
						printf("%d %d\n", path[i], path[i+1]);
					}
				}
//				printf("\n");
				break;	
			}

			// 如果可能,尝试机器人和障碍物的位置变换
/*			vector<int> this_array;
			for(int i = 0; i < m+1; i++)
				this_array.push_back(p->place[i]);
*/
			int not_free[20];
			memset(not_free, 0, sizeof(not_free));
			for(int i = 1; i <= n; i++)
				not_free[i] = (p->not_free_int & (1 << (n-i))) >> (n-i);
/*
			int this_int = 0;
			for(int i = 1; i <= n; i++)
				this_int = this_int*2 + p->not_free[i];
			int r_place = p->place[0];
*/		
			for(int i = 1; i <= n; i++)
			{
				if(not_free[i] == 0)
					continue;
//				int now_s = p->place[i];
				int now_s = i;
				for(int j = 0; j < next[now_s].size(); j++)
				{
					int now_t = next[now_s][j];
//					if(p->not_free[now_t] == 0)
					if(not_free[now_t] == 0)
					{
						int next_int = p->not_free_int - (1 << (n-now_s)) + (1 << (n-now_t));
						int next_r_place;
						if(i == p->r_place)
							next_r_place = now_t;
						else
							next_r_place = p->r_place;
						
/*						int tmp = this_array[i];
						this_array[i] = now_t;
						if(state_set.find(this_array) == state_set.end())		
				*/
						if(visit[next_int][next_r_place] == 0)
						{
			//				state_set.insert(this_array);
							visit[next_int][next_r_place] = 1;
							s_node* q = (s_node*)malloc(sizeof(s_node));
/*							for(int k = 0; k < m+1; k++)
//								q->place[k] = this_array[k];
								q->place[k] = p->place[k];
							q->place[i] = now_t;
							for(int k = 1; k <= n; k++)
								q->not_free[k] = p->not_free[k];
							q->not_free[now_s] = 0;
							q->not_free[now_t] = 1;
*/
							q->not_free_int = next_int;
							q->r_place = next_r_place;
			/*				for(int k = 0; k < p->path_length; k++)
								q->path[k] = p->path[k];
							q->path[p->path_length] = now_s;
							q->path[p->path_length+1] = now_t;
			*/
							q->from = now_s;
							q->to = now_t;
							q->path_length = p->path_length+1;
							q->parent = p;
							my_queue.push(q);
						}
//						this_array[i] = tmp;	
					}		
				}		
			}	
						
		}

		if(my_queue.size() == 0)
			printf("Case %d: -1\n", count+1);
		printf("\n");
		count++;		
	}
	return 0;	
}


这道题觉得可以用BFS,没有剪枝,TLE.

以为是剪枝的问题,看了别人的思路,要把状态压缩:数组压缩为整数。(哪些结点被占,机器人的位置)。两个数组压缩为两个整数,然后查表来确定该状态是否被遍历过,而不是用集合set来存储状态。仍然TLE, 将最后能优化的部分:每个节点不存全部的变换路径,而是只存自己变换的那一步,等到最后遍历到终点,再从该节点一直往上搜到根节点来打印路径。然后通过。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值