这个题目在比赛的时候我们是没有做出来的,但是听到他们说进制哈希的时候,感觉真的是挺高端的,于是赛后开始补题,本着我的习惯在看题解之前自己再试着写一遍,我当时存储状态的方法是string + map,我用string将蛇的各个位置都存下来,用map记录这个状态有没有出现过,当时是过了题目中给的样例,我就开始担心STL会不会超时,后来发现想多了,这个方法WA了,至于为什么,我还没明白,或许是状态的处理错误。总之我自己也觉得这个状态有点不靠谱。。于是开始换用题解的方式。发现所谓的进制哈希,其实就是状态压缩,我们的方向一共有4个,数组下标为0,1,2,3.二进制表示00,01,10,11.

  发现每一个方向都占用了两位,蛇身的长度(不包含蛇头)最大是7,所以方向状态最多有(1<<14)个,就可以使用vis[x][y][state]表示蛇头的位置和相对位置的状态压缩数值,在这里需要注意几个问题,vis为了节省空间和时间使用bool型的,state存储状态的时候让靠近蛇头的位置存储在低位。这样做的原因就是容易得到蛇移动以后的下一个状态,让它左移两位就可以。

  我自己也敲出了代码,但是出现了迷之bug,两个样例都没有过,所以我在别人的代码上加了注释(我的改对了估计就跟他的一模一样了),这是原博客地址,代码及注释如下:

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int MAX_S = ( << ) + ;
const int MAX_N = + ;
const int INF = ( << );
struct State
{
int x, y, dis, s;
State(int x = , int y = , int dis = , int s = ) : x(x), y(y), dis(dis), s(s) {};
};
struct POS
{
int x,y;
};
POS pos[MAX_N];
int N, M, res, L;
int vis[MAX_N][MAX_N][MAX_S];
int fx[] = {-, , , };
int fy[] = {, , , -};
bool _map[MAX_N][MAX_N];
queue <State> Q;
int get_start()
{
int dir, dx, dy, s = ;
for(int i = L - ; i > ; i--)///记录i如何走到i+1,便于回溯
{
dx = pos[i].x - pos[i - ].x, dy = pos[i].y - pos[i - ].y;
if(dx == && dy == )
dir = ;
else if(dx == && dy == -)
dir = ;
else if(dx == - && dy == )
dir = ;
else if(dx == && dy == )
dir = ;
s = s << ;
s = s | dir;
}
return s;
}
int get_next_state(int i, int s)
{
int dir;
int k = ( << ((L - ) << )) - ;///让(l-1)*2都是1,更高位为0
int dx = , dy = ;
dx = dx - fx[i], dy = dy - fy[i];///这里不要忘记将方向取反
if(dx == && dy == )
dir = ;
else if(dx == && dy == -)
dir = ;
else if(dx == - && dy == )
dir = ;
else if(dx == && dy == )
dir = ;
s = s << ;
s = s | dir;
s = s & k; /// 去除高位部分
return s;
} bool judge_code(int x, int y, int pre_x, int pre_y, int s)///判断会不会咬到自己
{
int dir;
for(int i = ; i < L - ; i++)
{
dir = ;
dir = dir & s;
s = s >> ;
if(x == pre_x + fx[dir] && y == pre_y + fy[dir])
return false;
pre_x = pre_x + fx[dir], pre_y = pre_y + fy[dir];
}
return true;
} void BFS()
{
State a;
int dx, dy, s;
while(!Q.empty())
{
a = Q.front();
Q.pop();
for(int i = ; i < ; i++)
{
dx = a.x + fx[i], dy = a.y + fy[i];
s = get_next_state(i, a.s);
if(dx > && dy > && dx <= N && dy <= M && !vis[dx][dy][s] && !_map[dx][dy] && judge_code(dx, dy, a.x, a.y, a.s))
{
if(dx == && dy == )
{
res = a.dis + ;
return ;
}
vis[dx][dy][s] = ;
Q.push(State(dx, dy, a.dis + , s));
}
}
}
} int main()
{
int s = , _case = ;
State _start;
while(scanf("%d%d%d", &N, &M, &L), N + M + L)
{
res = INF;
memset(_map, , sizeof(_map));
memset(vis, , sizeof(vis));
for(int i = ; i < L; i++)
scanf("%d%d", &pos[i].x, &pos[i].y);
int K, u, v;
scanf("%d", &K);
for(int i = ; i < K; i++)
{
scanf("%d%d", &u, &v);
_map[u][v] = ;
}
if(pos[].x == && pos[].y == )
{
printf("Case %d: 0\n", ++_case);
continue;
}
s = get_start();
Q.push(State(pos[].x, pos[].y, , s));
vis[pos[].x][pos[].y][s] = ;
BFS();
if(res == INF)
printf("Case %d: -1\n", ++_case);
else
printf("Case %d: %d\n", ++_case, res);
while(!Q.empty())
Q.pop();
}
return ;
}

UVALive 2520 Holedox Moving(BFS+状态压缩)的更多相关文章

  1. ACM/ICPC 之 BFS+状态压缩(POJ1324(ZOJ1361))

    求一条蛇到(1,1)的最短路长,题目不简单,状态较多,需要考虑状态压缩,ZOJ的数据似乎比POj弱一些 POJ1324(ZOJ1361)-Holedox Moving 题意:一条已知初始状态的蛇,求其 ...

  2. HDU1429+bfs+状态压缩

    bfs+状态压缩思路:用2进制表示每个钥匙是否已经被找到.. /* bfs+状态压缩 思路:用2进制表示每个钥匙是否已经被找到. */ #include<algorithm> #inclu ...

  3. BFS+状态压缩 hdu-1885-Key Task

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1885 题目意思: 给一个矩阵,给一个起点多个终点,有些点有墙不能通过,有些点的位置有门,需要拿到相应 ...

  4. poj 1753 Flip Game(bfs状态压缩 或 dfs枚举)

    Description Flip game squares. One side of each piece is white and the other one is black and each p ...

  5. BFS+状态压缩 HDU1429

    胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  6. hdoj 5094 Maze 【BFS + 状态压缩】 【好多坑】

    Maze Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Sub ...

  7. HDU 3247 Resource Archiver (AC自己主动机 + BFS + 状态压缩DP)

    题目链接:Resource Archiver 解析:n个正常的串.m个病毒串,问包括全部正常串(可重叠)且不包括不论什么病毒串的字符串的最小长度为多少. AC自己主动机 + bfs + 状态压缩DP ...

  8. UVALive 3956 Key Task (bfs+状态压缩)

    Key Task 题目链接: http://acm.hust.edu.cn/vjudge/contest/129733#problem/D Description The Czech Technica ...

  9. BFS+状态压缩DP+二分枚举+TSP

    http://acm.hdu.edu.cn/showproblem.php?pid=3681 Prison Break Time Limit: 5000/2000 MS (Java/Others)   ...

随机推荐

  1. PQ分区魔术师v9.0 中文版

    软件名称: pqmagic 硬盘分区大师9.0中文绿色版 软件大小:5.80MB 软件语言:简体中文 软件类别:磁盘工具 软件授权:免费软件 更新时间:2013-10-082013-10-08 09: ...

  2. UIDatePicker 时间滚动表

    UIDatePicker *datapicker; //时间滚动表 datapicker = [[UIDatePicker alloc]initWithFrame:CGRectMake(50, 200 ...

  3. 百度地图api写在html上可以实现,在jsp上会出现Bmap未定义的问题

    在html上引用时用:<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0& ...

  4. uiwebview 加载html时字体变小 加载前或加载后改变字体大小

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #6122ae } p.p2 { margin: 0.0px 0. ...

  5. angular localStorage使用方法

    var YourCtrl = function($scope, localStorageService, ...) { // To add to local storage localStorageS ...

  6. Struts2 Spring3 Hibernate3 集成xml版本

    Struts2 Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互 ...

  7. mysql 查询语句

    查询一段时间到另一段时间的数据 $from=$_POST['from']; $to=$_POST['to']; $query_xiangmu ="SELECT * FROM yichang ...

  8. 《JavaScript高级程序设计》读书笔记 ---小结

    对象在JavaScript 中被称为引用类型的值,而且有一些内置的引用类型可以用来创建特定的对象,现简要总结如下: 引用类型与传统面向对象程序设计中的类相似,但实现不同: Object 是一个基础 ...

  9. 郑州尚学堂:链表的C语言如何实现动态内存分配

    一.为什么用动态内存分配 但我们未学习链表的时候,如果要存储数量比较多的同类型或同结构的数据的时候,总是使用一个数组.比如说我们要存储一个班级学生的某科分数,总是定义一个float型(存在0.5分)数 ...

  10. C# cookies

    谷歌浏览器- 工具---internet选项---常规---浏览历史记录---设置  cookie和网站数据 C:\Documents and Settings\Administrator\Local ...