题目链接:Holedox Moving POJ - 1324

===================================================

Holedox Moving

Time Limit: 5000 ms
Memory Limit: 65536 kB

Description

During winter, the most hungry and severe time, Holedox sleeps in its lair. When spring comes, Holedox wakes up, moves to the exit of its lair, comes out, and begins its new life.
Holedox is a special snake, but its body is not very long. Its lair is like a maze and can be imagined as a rectangle with n*m squares. Each square is either a stone or a vacant place, and only vacant places allow Holedox to move in. Using ordered pair of row and column number of the lair, the square of exit located at (1,1).

Holedox’s body, whose length is L, can be represented block by block. And let B1(r1,c1) B2(r2,c2) … BL(rL,cL) denote its L length body, where Bi is adjacent to Bi+1 in the lair for 1 <= i <=L-1, and B1 is its head, BL is its tail.

To move in the lair, Holedox chooses an adjacent vacant square of its head, which is neither a stone nor occupied by its body. Then it moves the head into the vacant square, and at the same time, each other block of its body is moved into the square occupied by the corresponding previous block.

For example, in the Figure 2, at the beginning the body of Holedox can be represented as B1(4,1) B2(4,2) B3(3,2)B4(3,1). During the next step, observing that B1’(5,1) is the only square that the head can be moved into, Holedox moves its head into B1’(5,1), then moves B2 into B1, B3 into B2, and B4 into B3. Thus after one step, the body of Holedox locates in B1(5,1)B2(4,1)B3(4,2) B4(3,2) (see the Figure 3).

Given the map of the lair and the original location of each block of Holedox’s body, your task is to write a program to tell the minimal number of steps that Holedox has to take to move its head to reach the square of exit (1,1).

Input

The input consists of several test cases. The first line of each case contains three integers n, m (1<=n, m<=20) and L (2<=L<=8), representing the number of rows in the lair, the number of columns in the lair and the body length of Holedox, respectively. The next L lines contain a pair of row and column number each, indicating the original position of each block of Holedox’s body, from B1(r1,c1) to BL(rL,cL) orderly, where 1<=ri<=n, and 1<=ci<=m,1<=i<=L. The next line contains an integer K, representing the number of squares of stones in the lair. The following K lines contain a pair of row and column number each, indicating the location of each square of stone. Then a blank line follows to separate the cases.

The input is terminated by a line with three zeros.

Note: Bi is always adjacent to Bi+1 (1<=i<=L-1) and exit square (1,1) will never be a stone.

Output

For each test case output one line containing the test case number followed by the minimal number of steps Holedox has to take. “-1” means no solution for that case.

Sample Input

5 6 4
4 1
4 2
3 2
3 1
3
2 3
3 3
3 4

4 4 4
2 3
1 3
1 4
2 4
4

2 1
2 2
3 4
4 2

0 0 0

Sample Output

Case 1: 9
Case 2: -1

===================================================

题意:一个n,m的巢穴地图,里面有石头不能走,洞口永远为(1,1)。然后给你一条长度L[2,8]的蛇。然后蛇每一次移动,身体也会跟着走,然后你不能穿过石头和身体。问你到洞口的最短步数是多少?

算法:A*+状态压缩

思路:

  • 这里启发函数就直接蛇头与洞口曼哈顿距离就行了;
  • 判重函数:这里每个点维护的信息:蛇头坐标,步数,蛇身体状态;其实区分每一个点入队的判重,这里就重要是蛇头和身体状态(因为身体也会阻碍蛇头前进);蛇头直接二维x,y就行了;然后就是蛇身体如何区分记录呢?一开始我的想法是,最大长度为8,那再记录身体其他坐标就好了,但是21的16次方直接爆了,MLE。然后想了很久,还是看了别人博客,学到了。只要记录蛇头,然后第二节只要记录方向就行,第三节只要记录相对于第二节的方向就行了,等等。因为方向只有4个方向,所以 最大只要 4的7次方 就是 2 的14次方;所以开三维,vis[21][21][1<<14]

难点:

  • 我直接1A了,没有什么地方出错;求方向四进制状态、还原身体坐标、维护新的四进制状态这几个可能会比较容易搞得混乱,我自己也码的不好看,但也懒得改了,希望能帮到你

===================================================

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdio>using namespace std;const int INF = 0x3f3f3f3f;
const int MAXN = 1010;int four[7];//四进制基数
int n,m;//迷宫长宽
int stNum;bool ditu[21][21];//石头数+地图标记
int snakeNum;//蛇的长度
int snakeHeadX,snakeHeadY,snakeBody;//蛇头坐标  + 蛇形状的四进制表示(用四进制记录每一节对于前一节的方向)
bool vis[21][21][1<<14];//蛇头坐标  + 蛇形状的四进制表示 de  三维标记判重函数
int xx[] = {0,1,0,-1};
int yy[] = {1,0,-1,0};//用于求蛇身每一节对于前一节的方向,0,1,2,3,分别表示右下左上
int check(int a,int b,int c,int d){if(c-a==0&&d-b==1) return 0;if(c-a==1&&d-b==0) return 1;if(c-a==0&&d-b==-1) return 2;if(c-a==-1&&d-b==0) return 3;
}//初始输入+预处理
void init(){cin>>snakeHeadX>>snakeHeadY;int a=snakeHeadX,b=snakeHeadY,c,d;snakeBody=0;for(int i=0;i<snakeNum-1;i++){cin>>c>>d;snakeBody+=four[i]*check(a,b,c,d);a=c,b=d;}cin>>stNum;memset(ditu,true,sizeof ditu);for(int i=0;i<stNum;i++){cin>>a>>b;ditu[a][b]=false;}
}//测试函数 可删除
void show(){cout<<n<<" "<<m<<" "<<snakeNum<<endl;cout<<snakeHeadX<<" "<<snakeHeadY<<" "<<snakeBody<<endl;for(int i=0;i<snakeNum-1;i++){int tmp = snakeBody % 4;cout<<tmp<<" ";snakeBody/=4;}cout<<endl;cout<<stNum<<endl;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) cout<<ditu[i][j]<<" ";cout<<endl;}
}//蛇头X,Y坐标 蛇的四进制表示  启发函数数值f(这里是蛇头与洞口(1,1)的曼哈顿距离)
struct node{int x,y,snake,step,f;node(int xx,int yy,int ssnake,int sstep):x(xx),y(yy),snake(ssnake),step(sstep){f=step+abs(x-1)+abs(y-1);}bool operator < (const node &a) const{return f > a.f;}
};//这个函数是通过 蛇头坐标 蛇身四进制 来求 蛇身坐标数组 和 蛇尾对于前一节的方向
void snakeXY(int SX,int SY,int (&snakeX)[8],int (&snakeY)[8],int &c,int d){int x = SX,y = SY;for(int i=0;i<snakeNum-1;i++){int tmp = d % 4; d/=4;x+=xx[tmp],y+=yy[tmp];snakeX[i] = x ,snakeY[i] = y ;if(i==snakeNum-2) c = tmp;}
}//判断蛇头是否能走(x,y)
bool checkN(int x,int y,int a[],int b[]){if(x<=0||x>n||y<=0||y>m||ditu[x][y]==false) return false;for(int i=0;i<snakeNum-1;i++){if(x==a[i]&&y==b[i]) return false;}return true;
}//A*算法
int Astar(){memset(vis,false,sizeof vis);priority_queue<node> q;q.push(node(snakeHeadX,snakeHeadY,snakeBody,0));vis[snakeHeadX][snakeHeadY][snakeBody] = true;while(!q.empty()){node p = q.top();q.pop();if(p.x==1&&p.y==1) return p.step;//这里记录蛇身坐标 和 蛇尾方向int snakeX[8],snakeY[8],tail;snakeXY(p.x,p.y,snakeX,snakeY,tail,p.snake);//右、下、左、上for(int i=0;i<4;i++){int x = p.x + xx[i],y = p.y + yy[i];if(!checkN(x,y,snakeX,snakeY)) continue;//这里开始算新的方向四进制  去尾加头int body = p.snake - four[snakeNum-2]*tail;body*=4;if(i==0) body+=2;else if(i==1) body+=3;else if(i==2) body+=0;else body += 1;if(vis[x][y][body]) continue;vis[x][y][body] = true;q.push(node(x,y,body,p.step+1));}}return -1;
}int main()
{four[0]=1;for(int i=1;i<7;i++) four[i] = four[i-1]*4;int _=1;while(cin>>n>>m>>snakeNum&&n&&m&&snakeNum){init();cout<<"Case "<<_++<<": ";cout<<Astar()<<endl;}return 0;
}

Holedox Moving POJ - 1324相关推荐

  1. poj 1324 Holedox Moving

    poj 1324 Holedox Moving 题目地址: http://poj.org/problem?id=1324 题意: 给出一个矩阵中,一条贪吃蛇,占据L长度的格子, 另外有些格子是石头, ...

  2. poj 1729 Jack and Jill 1376 Robot 1324 Holedox Moving 1475 Pushing Boxes bfs + a*

    poj 1729 Jack and Jill Jack和Jill要从各自的家走到各自的学校,但是他们俩各自不喜欢对方,因此,需要你找到两个人行走的路线,使得他们路线中两个人最近的直线距离最长.单位时间 ...

  3. POJ 1324 Holedox Moving 搜索

    题目地址: http://poj.org/problem?id=1324 优先队列---A*的估价函数不能为蛇头到(1,1)的距离,这样会出错. 看了discuss,有大神说这题A*的估价函数为BFS ...

  4. Poj 1324 Holedox Moving 状压判重+BFS

    模拟类似贪吃蛇运动,问蛇头最少移动几格到1,1 BFS好题,状态vis[20][20][16384]来存蛇头的位置,和后面每一节想对于前面一节的关系,四个方向用0,1,2,3存,需要14位 #incl ...

  5. poj 1324(BFS+状态压缩)

    解题思路:这道题一开始的想法就是状态压缩,即考虑如何判重,由于蛇并非是直线的,所以想到了以每一个点的上下左右共四个 值来表示相对位置.最开始想如何用四进制来表示它,无语.....还是题目做少了,直接用 ...

  6. Holedox Moving

    2012-08-11  我的第一个A*算法: 四处看A*算法..还是有一点没有弄明白就是那个当已经在列表中的时候再次进入的时候怎么去更新. 这道题..有点难开始的时候不会位压缩,去看了一个别人的代码. ...

  7. poj 1324 Astar

    /* 题意:贪吃蛇,求到(1,1)的最短路径题解:A_star搜索 感觉不完全是A*,也许有更好的做法,估价函数为(x-1+y-1),比网上说的先用BFS搜索一遍求估价值要快=.= */ #inclu ...

  8. POJ1324 Holedox Moving(BFS)

    有一条蛇蜿蜒在洞穴里面,出口为(1,1),问(蛇头)走出洞口的最小步数.走的过程不能碰到自己的身体也不能碰到石头.蛇头每移动一格,身体也要相应的移动一格.(注意:貌似当前蛇头不能移动到当前蛇尾的位置) ...

  9. 红书上的几道搜索例题

    Holedox Moving poj 1324 题意:贪吃蛇,n*m的网格,蛇长度<=8,给出蛇的每个身体的位置,求到(1,1)点的最短距离 http://www.cnblogs.com/lon ...

最新文章

  1. TFS的Web门户工作项(七)
  2. CentOS下安装protobuf
  3. 在64位Windows7上安装64位Oracle11g
  4. 基于Matlab的标记分水岭分割算法(imreconstruct)
  5. 计算机与生命科学交叉应用,第二届 “数学、计算机与生命科学交叉研究”青年学者论坛...
  6. java密钥库文件存在但为空_java安全套接层SSL示例
  7. 自学Python能干些什么副业
  8. 前端 如何检测到当前的网页已经退出_javascript在当前窗口关闭前检测窗口是否关闭...
  9. html5微信视频禁止自动全屏,关于HTML5 video标签在安卓版微信浏览器内被强行全屏播放的问题...
  10. good nice fine well区别
  11. NYOJ201-作业题(最长升降子序列)
  12. canvas设置字体粗细用数字没效果_干货 | 用uni-app制作迷你PS小程序
  13. Atitit.设计模式-----触发器模式 trigger  详解
  14. 使用 PotPlayer 搭配 SVP 4 播放60帧电影
  15. fanuc机器人示教器输入中文注释
  16. MongoDB实战(MongoDB开发者现身说法)
  17. Golang与Java各方面使用对比(下)
  18. 这篇文章让你轻松实现流动图片
  19. android java 线程通信_Android 线程间通信
  20. systemctl笔记221029

热门文章

  1. Ubuntu的Intel网卡驱动安装
  2. 嘟嘟投资升级笔记 -- 懂得这几招,投资菜鸟变老鸟
  3. 云服务器传文件用什么软件,免费云主机文件传输软件推荐,大文件极速秒传
  4. Windows 10 无法访问某文件夹(如C:\Documents and Settings)。拒绝访问。解决方法
  5. 5个 Word 小技巧,能够让你在制作和排版文档时如有神助
  6. 子集构造法和含有空串的子集构造法
  7. 21、SQL Server 数据修改之Delete
  8. Nginx流量拦截算法 1
  9. 1119-期货要见好就收
  10. 如何对企业网站进行优化?(网站怎样优化seo)