基本思路就是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 (EASY Version) (BFS+状态压缩)

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

  2. UVA12569-Planning mobile robot on Tree (EASY Version)(BFS+状态压缩)

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

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

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

  4. Codeforces Round #540 (Div. 3) F1. Tree Cutting (Easy Version) 【DFS】

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

  5. Leetcode之101. 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 (Easy Version)(DFS)

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

  7. ZOJ 3868 - Earthstone: Easy Version

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

  8. Codeforces 1077F1 Pictures with Kittens (easy version)(DP)

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

  9. Coffee and Coursework (Easy version)

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

随机推荐

  1. bmob云 实现注册和登录的功能

    向大家介绍一款我感觉非常溜的一款后端云服务bmob云 借助bmob云我们可以实现注册和登录页面的功能,下面就让我给大家演示一下借助bmob云服务实现这两个功能吧.  1. 用户是一个应用程序的核心.对 ...

  2. 火狐浏览器开始支持3D游戏和视屏通话

    最近,Mozilla发布了第22版本的火狐浏览器,这个版本增加了对3D游戏.视频通话和文件分享功能的支持.现在使用者不必下载额外的插件或者第三方软件就可以使用上面的所有特性.为了鼓励更多的开发者为火狐 ...

  3. untiy 播放视频

    利用 MovieTexture 类 放入视频 视频不能使flv的 建立一个平面 作为屏幕,利用Material 播放动画,剩下的就是将平面放大和屏幕一样/ public MovieTexture My ...

  4. eclipse集成jetty开发web项目(不采用maven方式)

    以前开发过程部署项目都是采用tomcat,偶然发现jetty,所以试了下,挺方便的,直切主题. 1.下载jetty,楼主使用的jetty8,地址http://download.eclipse.org/ ...

  5. 利用fitnesse实现api接口自动化测试

    上午在园子里乱逛,看了不少小伙伴们分享的接口测试方面的知识,仔细想想,我做接口测试也有几个年头了,大家所叙述到的一些经验或多或少,我也曾遇到过,突然意识到知识的点滴积累是多么的重要,我记得我最早接触接 ...

  6. 转几篇关于Android webView的网文

    1,控件WebView显示网页 http://www.cnblogs.com/tinyphp/p/3858997.html http://blog.csdn.net/t12x3456/article/ ...

  7. poj 2417

    Accepted 8508K 391MS C++ 2004B 相比下边,,优化太多太多了... /** baby-step-giant-step 因为数据量太大,,自己写hash **/ #inclu ...

  8. nrf51 SDK自带例程的解读

    简单的pwm电机控制示例 simple_pwm_motor_control_example 其实就是pwm控制led的亮度 1.首先设置gpiote 设置初始为高电平2.接着设置ppi 定时器time ...

  9. PowerShell Remove all user defined variable in PowerShell

    When PS scripts executes, it is possibly create much user defined variables. So, sometimes these var ...

  10. Windows Azure 社区新闻综述(#74 版)

    欢迎查看最新版本的每周综述,其中包含有关云计算和 Windows Azure 的社区推动新闻.内容和对话.以下是本周的亮点. 文章.视频和博客文章 ·   Azure CDN:吸取的宝贵经验(10 月 ...