Uva 12569 Planning mobile robot on Tree (EASY Version)

时间:2022-10-21 13:18:07

基本思路就是Bfs:

  本题的一个关键就是如何判段状态重复。

  1.如果将状态用一个int型数组表示,即假设为int state[17],state[0]代表机器人的位置,从1到M从小到大表示障碍物的位置。那么如果直接用STL中的set是会超时的,但如果自己建立一个hash方法,像这样:   

int getKey(State& s) {
long long v = 0;
for(int i=0; i<=M; ++i ) {
v = v * 10 + s[i];
}
return v % hashSize;
}

是可以避免超时的。

  2. 除了上面这种,还有一种方法是用二进制法,因为有15个位置,除了robot,每个位置的状态只有 "有"或"无",可以分别用1或0表示,那么就是15位的二进制,如

    00000 00000 00001 可以表示位置0存在一个障碍物, 转化为int型整数即为 1

    11111 00000 11111 可以表示位置0~4, 10~14各存在一个障碍物,转化为int型整数即为31775

    那么所有障碍物的状态可以在0~2^15-1的范围内表示出来,另外单独考虑robot的位置,可以用一个bool数组,如 bool vis[32767][15]表示

      每次移动障碍物时,先确定移动的起始位置(二进制为1的位置),再确定目标位置(二进制为0且与robot不重合的位置)。

    同样机器人移动也是类似的道理。

    因为采用了位运算,而且判重方法比上一种相对来得简单,所以速度要比上一种方法快一点。

PS:做这题时,刚开始采用了STL的set方法,结果超时。之后采用了自建hash表的方法,过了,但时间处于5000ms这个级别。后来观察别人的代码,才发现别人采用了二进制的方法(点击查看),自己才恍然大悟,原理还可以这么做!!!于是自己琢磨了一下,写了一下,并且AC,发现速度大增,马上处于1000ms的级别。

#include <bits/stdc++.h>

using namespace std;

const int MAXN = (1 << 15) + 50;
bool vis[MAXN][15+2];
struct Node{
int robot, ob, step;
};
typedef pair<int, int> Move; // from first to second
Node q[MAXN*17]; // queue
Move move[MAXN*17];
int movePath[MAXN*17]; // the step before rear is movePath[rear]
vector <int> link[17]; // link table
int n, m, s, target;
int start; void Read() {
cin >> n >> m >> s >> target;
start = 0;
s --;
target --;
int tmp;
for(int i=0; i<m; ++i) {
cin >> tmp;
start = start | (1 << (tmp - 1)); // add ob at position tmp-1
}
for(int i=0; i<n; ++ i) {
link[i].clear();
}
int x, y;
for(int i=0; i<n-1; ++i) {
cin >> x >> y;
link[x-1].push_back(y-1);
link[y-1].push_back(x-1);
}
} // print path
void Print(int rear) {
vector<Move> v;
while(rear) {
v.push_back(move[rear]);
rear = movePath[rear];
}
vector<Move>::iterator it;
for(it = v.end()-1; it>=v.begin(); it--) {
// +1 !!!
cout << it->first + 1 << " " << it->second + 1 << endl;
}
} void Bfs() {
int front = 0, rear = 1;
q[front].ob = start;
q[front].robot = s;
q[front].step = 0;
memset(vis, false, sizeof(vis));
vis[q[front].ob][q[front].robot] = true;
while(front < rear) {
Node& t = q[front];
if(t.robot == target) {
cout << t.step << endl;
Print(front);
return ;
}
for(int i=0; i<n; ++i) { // move i
if((t.ob & (1 << i)) || i == t.robot) {
// there is an ob or a robot at the position
for(size_t j=0; j<link[i].size(); ++ j) {
int nextNode = link[i][j];
if(nextNode == t.robot || ((1<<nextNode) & t.ob)!=0 ) {
// there exists an ob or a robot at the next position
continue;
}
Node next = t;
if(i == t.robot) {
next.robot = nextNode;
} else {
// move from i to nextNode
next.ob = next.ob - (1 << i);
next.ob = next.ob + (1 << nextNode);
}
next.step = t.step + 1;
if(!vis[next.ob][next.robot]) {
vis[next.ob][next.robot] = true;
move[rear].first = i; // from
move[rear].second = nextNode; // next
movePath[rear] = front; // the former step
q[rear ++] = next; // push into the queue
}
}
}
}
++ front;
}
cout << -1 << endl;
} int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T, Case = 0;
cin >> T;
while(T --) {
Read();
cout << "Case " << (++Case) << ": ";
Bfs();
}
return 0;
}

Uva 12569 Planning mobile robot on Tree (EASY Version)的更多相关文章

  1. UVA-12569 Planning mobile robot on Tree &lpar;EASY Version&rpar; (BFS&plus;状态压缩)

    题目大意:一张无向连通图,有一个机器人,若干个石头,每次移动只能移向相连的节点,并且一个节点上只能有一样且一个东西(机器人或石头),找出一种使机器人从指定位置到另一个指定位置的最小步数方案,输出移动步 ...

  2. UVA12569-Planning mobile robot on Tree &lpar;EASY Version&rpar;(BFS&plus;状态压缩)

    Problem UVA12569-Planning mobile robot on Tree (EASY Version) Accept:138  Submit:686 Time Limit: 300 ...

  3. UVA Planning mobile robot on Tree树上的机器人(状态压缩&plus;bfs)

    用(x,s)表示一个状态,x表示机器人的位置,s表示其他位置有没有物体.用个fa数组和act数组记录和打印路径,转移的时候判断一下是不是机器人在动. #include<bits/stdc++.h ...

  4. Codeforces Round &num;540 &lpar;Div&period; 3&rpar; F1&period; Tree Cutting &lpar;Easy Version&rpar; 【DFS】

    任意门:http://codeforces.com/contest/1118/problem/F1 F1. Tree Cutting (Easy Version) time limit per tes ...

  5. Leetcode之101&period; Symmetric Tree Easy

    Leetcode 101. Symmetric Tree Easy Given a binary tree, check whether it is a mirror of itself (ie, s ...

  6. Ping-Pong &lpar;Easy Version&rpar;(DFS)

    B. Ping-Pong (Easy Version) time limit per test 2 seconds memory limit per test 256 megabytes input ...

  7. ZOJ 3868 - Earthstone&colon; Easy Version

    3868 - Earthstone: Easy Version Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld ...

  8. Codeforces 1077F1 Pictures with Kittens &lpar;easy version&rpar;(DP)

    题目链接:Pictures with Kittens (easy version) 题意:给定n长度的数字序列ai,求从中选出x个满足任意k长度区间都至少有一个被选到的最大和. 题解:$dp[i][j ...

  9. Coffee and Coursework &lpar;Easy version&rpar;

    Coffee and Coursework (Easy version) time limit per test 1 second memory limit per test 256 megabyte ...

随机推荐

  1. WPF - MVVM - 如何将ComboBox的Selectchange事件binding到ViewModel

    转:http://www.cnblogs.com/mantian/p/3713524.html 将所有的事件,属性,都映射到ViewModel中.好处多多,以后开发尽量用这种模式. 解决方法: 使用S ...

  2. 初识Groovy

    Groovy是一种基于JVM(Java虚拟机)的敏捷开发语言,它结合了Python.Ruby和Smalltalk的许多强大的特性,Groovy 代码能够与 Java 代码很好地结合,也能用于扩展现有代 ...

  3. Android Activity之间通信

    package com.example.myapp; import android.app.Activity; import android.content.DialogInterface; impo ...

  4. jQuery第三章

    一.jQuery中的DOM操作 一般来说,DOM操作分为3个方面,即DOM Core核心.HTML-DOM和CSS-DOM 1.DOM Core JavaScript中的getElementById( ...

  5. C&num;设计模式之十组合模式(Composite)【结构型】

    一.引言   今天我们要讲[结构型]设计模式的第四个模式,该模式是[组合模式],英文名称是:Composite Pattern.当我们谈到这个模式的时候,有一个物件和这个模式很像,也符合这个模式要表达 ...

  6. 解决来自美国IP的攻击过程

    1.因为最近接口文档confluence服务总是自动关闭.   解决方法: 1.查看阿里云上的报警提示,看到来自外国的Ip的攻击.这时我选择把攻击的IP加入黑名单. 加入黑名单的方法:https:// ...

  7. 服务调用框架DataStrom

    根据以前的命名服务,从新构建了下服务框架: 结构模式:c-center-s; 1.服务端: 服务端启动,讲自己的IP,端口注册到注册中心节点(master),然后注册自己的处理类(需要继承对应接口); ...

  8. 本博客停止更新改用wordperss

    http://www.azurew.com/ 还是能有自己的博客比较爽 哈哈哈

  9. Centos下普通用户设置sudo权限

    若执行sudo命令的用户没有sodu权限,则会报以下错误 violet is not in the sudoers file.This incident will be reported 若想让vio ...

  10. 每日linux命令学习-sed

    Linux的文本处理实用工具主要由sed和awk命令,二者虽然略有差异,但都使用正则表达式,默认使用标准I/O,并且使用管道命令可以将前一个命令的输出作为下一个命令的输入.笔者将在本节学习sed命令. ...