题目地址: http://poj.org/problem?id=1324

优先队列---A*的估价函数不能为蛇头到(1,1)的距离,这样会出错。

看了discuss,有大神说这题A*的估价函数为BFS (0,0)到各点的花费在乘上10 ,但是还是不清楚,希望知道的可以给我留个言,谢谢了。

思路:

用0,1,2,3表示方向,这样就可以用四进制状态压缩了。

总共需要3+3*4^1+……3*4^6.

推荐大家能不用STL就不用STL,太浪费时间了。

下面是用STL超时代码和用数组模拟AC代码。

超时代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std; typedef long long LL;
const int N=21;
const LL II=1000000007; int n,m,L;
int maps[N][N];//0代表空,1代表蛇身体,2代表石头
bool vis[N][N][17000];//状态压缩
int t[4][2]={0,-1,1,0,0,1,-1,0}; struct xh
{
int step;
int po[11][2];
}w,e; int location(int px,int py,int nx,int ny)//求两个节点的相对位置
{
if(px==nx)
{
if(py>ny)
return 0;
else
return 1;
}
else
{
if(px>nx)
return 2;
else
return 3;
}
} int gethash(int B[][2])
{//得到状态
int s=0;
for(int i=0;i<L-1;i++)
s=s*4+location(B[i][0],B[i][1],B[i+1][0],B[i+1][1]);
return s;
} bool inmap(int x,int y,xh a)
{
if(!(x>=1&&x<=n&&y>=1&&y<=m))
return false;
if(maps[x][y]==2)
return false;
for(int i=0;i<L;i++)//蛇头和蛇尾相连也不行的
if(x==a.po[i][0]&&y==a.po[i][1])//判断是否这一步为蛇身
return false;
return true;
} void bfs()
{
int i,j,hash,x,y;
w.step=0;
hash=gethash(w.po);
x=w.po[0][0]; y=w.po[0][1];
vis[x][y][hash]=true;
queue<xh> q;
q.push(w);
if(x==1&&y==1)
{
printf("0\n");
return ;
}
while(!q.empty())
{
e=q.front();
q.pop();
for(i=0;i<4;i++)
{
w=e;
x=w.po[0][0]; y=w.po[0][1];
x+=t[i][0]; y+=t[i][1];
if(!inmap(x,y,w)) continue;
for(j=L-1;j>=1;j--)
{
w.po[j][0]=w.po[j-1][0];
w.po[j][1]=w.po[j-1][1];
}
w.po[0][0]=x; w.po[0][1]=y;
hash=gethash(w.po);
if(vis[x][y][hash]) continue;
vis[x][y][hash]=true;
w.step++;
q.push(w);
if(x==1&&y==1)
{
printf("%d\n",w.step);
return ;
}
}
}
printf("-1\n");
} int main()
{
int i,k,ci=0;
while(scanf("%d%d%d",&n,&m,&L)&&(n+m+L))
{
memset(maps,0,sizeof(maps));
memset(vis,false,sizeof(vis));
for(i=0;i<L;i++)
{
scanf("%d%d",&w.po[i][0],&w.po[i][1]);
}
scanf("%d",&k);
while(k--)
{
int a,b;
scanf("%d%d",&a,&b);
maps[a][b]=2;//石头
}
printf("Case %d: ",++ci);
bfs();
}
return 0;
}

用STL写就超时了,用数组模拟就过了

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std; typedef long long LL;
const int N=21;
const LL II=1000000007; int n,m,L;
int maps[N][N];//0代表空,1代表蛇身体,2代表石头
bool vis[N][N][17000];//状态压缩
int t[4][2]={0,-1,1,0,0,1,-1,0}; struct xh
{
int step;
int po[11][2];
}w,e,q[5000004]; int location(int px,int py,int nx,int ny)//求两个节点的相对位置
{
if(px==nx)
{
if(py>ny)
return 0;
else
return 1;
}
else
{
if(px>nx)
return 2;
else
return 3;
}
} int gethash(int B[][2])
{//得到状态
int s=0;
for(int i=0;i<L-1;i++)
s=s*4+location(B[i][0],B[i][1],B[i+1][0],B[i+1][1]);
return s;
} bool inmap(int x,int y,xh a)
{
if(!(x>=1&&x<=n&&y>=1&&y<=m))
return false;
if(maps[x][y]==2)
return false;
for(int i=0;i<L;i++)//蛇头和蛇尾相连也不行的
if(x==a.po[i][0]&&y==a.po[i][1])//判断是否这一步为蛇身
return false;
return true;
} void bfs()
{
int i,j,hash,x,y,head=0,tail=0;
w.step=0;
hash=gethash(w.po);
x=w.po[0][0]; y=w.po[0][1];
vis[x][y][hash]=true;
q[tail++]=w;
if(x==1&&y==1)
{
printf("0\n");
return ;
}
while(head<tail)
{
e=q[head++];
for(i=0;i<4;i++)
{
w=e;
x=w.po[0][0]; y=w.po[0][1];
x+=t[i][0]; y+=t[i][1];
if(!inmap(x,y,w)) continue;
for(j=L-1;j>=1;j--)
{
w.po[j][0]=w.po[j-1][0];
w.po[j][1]=w.po[j-1][1];
}
w.po[0][0]=x; w.po[0][1]=y;
hash=gethash(w.po);
if(vis[x][y][hash]) continue;
vis[x][y][hash]=true;
w.step++;
q[tail++]=w;
if(x==1&&y==1)
{
printf("%d\n",w.step);
return ;
}
}
}
printf("-1\n");
} int main()
{
int i,k,ci=0;
while(scanf("%d%d%d",&n,&m,&L)&&(n+m+L))
{
memset(maps,0,sizeof(maps));
memset(vis,false,sizeof(vis));
for(i=0;i<L;i++)
{
scanf("%d%d",&w.po[i][0],&w.po[i][1]);
}
scanf("%d",&k);
while(k--)
{
int a,b;
scanf("%d%d",&a,&b);
maps[a][b]=2;//石头
}
printf("Case %d: ",++ci);
bfs();
}
return 0;
}

POJ 1324 Holedox Moving 搜索的更多相关文章

  1. poj 1324 Holedox Moving

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

  2. POJ 1324 Holedox Moving (状压BFS)

    POJ 1324 Holedox Moving (状压BFS) Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 18091 Acc ...

  3. POJ - 1324 Holedox Moving (状态压缩+BFS/A*)

    题目链接 有一个n*m(1<=n,m<=20)的网格图,图中有k堵墙和有一条长度为L(L<=8)的蛇,蛇在移动的过程中不能碰到自己的身体.求蛇移动到点(1,1)所需的最小步数. 显然 ...

  4. poj 1324 状态压缩+bfs

    http://poj.org/problem?id=1324 Holedox Moving Time Limit: 5000MS   Memory Limit: 65536K Total Submis ...

  5. poj1324 Holedox Moving

    Holedox Moving Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 16980   Accepted: 4039 D ...

  6. POJ.3279 Fliptile (搜索+二进制枚举+开关问题)

    POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...

  7. POJ 1475 Pushing Boxes 搜索- 两重BFS

    题目地址: http://poj.org/problem?id=1475 两重BFS就行了,第一重是搜索箱子,第二重搜索人能不能到达推箱子的地方. AC代码: #include <iostrea ...

  8. poj 3279 Fliptile (简单搜索)

    Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16558   Accepted: 6056 Descrip ...

  9. poj 1198 hdu 1401 搜索+剪枝 Solitaire

    写到一半才发现能够用双向搜索4层来写,但已经不愿意改了,干脆暴搜+剪枝水过去算了. 想到一个非常水的剪枝,h函数为  当前点到终点4个点的最短距离加起来除以2.由于最多一步走2格,然后在HDU上T了, ...

随机推荐

  1. php中include文件变量作用域的研究

    原文:php中include文件变量作用域的研究 在php中我们有时候需要include一个文件.比如我前段时间在写一个框架的时候,打算用原生的php作为模板,然后写一个display方法引入模板文件 ...

  2. hadoop(六) - ZooKeeper安装与配置

    一. ZooKeeper配置 1.使用winscp上传zk安装包 zookeeper-3.4.5.tar.gz 2.解压安装包tar -zxvf zookeeper-3.4.5.tar.gz -C / ...

  3. Swift - 协议(protocol)

    1,Swift中协议类似于别的语言里的接口,协议里只做方法的声明,包括方法名.返回值.参数等信息,而没有具体的方法实现. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  4. 每次调用fork()函数之后,父线程和创建出的子线程都是从fork()后开始执行

    Linux下多少个"-"将被打印: 1 2 3 4 5 6 7 8 int main(void){   int i;   for(i=0;i<4;i++){   fork() ...

  5. jquery 学习 (二)

    1)jquery对象和dom对象区别及相互转换 2)jquery和其他库冲突解决 3)css选择器和jquery选择器 3.1)基本选择器(id选择器.类选择器.元素选择器.*选择器.多个选择器以逗号 ...

  6. delphi 自我删除和线程池(1000行代码,需要仔细研究)

    unit Unit4; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. IOS7最新的系统漏洞

    苹果近期就实用户发现了一个新iOS7系统漏洞,利用这个漏洞绕过password输入界面,在不知道password的情况下打开你近期使用的软件. 而这个过程仅仅需短短的5秒钟! 经測试,这个漏洞并没那么 ...

  8. POJ 3414 Pots 记录路径的广搜

    Description You are given two pots, having the volume of A and B liters respectively. The following ...

  9. socket网络编程的一些基础知识

    源地址:http://blog.csdn.net/roger_77/article/details/1453049 目录: 1) 什么是套接字? 2) Internet 套接字的两种类型 3) 网络理 ...

  10. EA强大功能之代码凝视

    前面讲了EA怎样方便我们生成代码,这次讲一下,怎样生成具体的凝视. 1.文件表头凝视 (1)点击工具----选项 在常规项里改动作者: 在代码project中改动代码project的默认语言. (2) ...