POJ 1324 Holedox Moving 搜索
题目地址: 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 搜索的更多相关文章
- poj 1324 Holedox Moving
poj 1324 Holedox Moving 题目地址: http://poj.org/problem?id=1324 题意: 给出一个矩阵中,一条贪吃蛇,占据L长度的格子, 另外有些格子是石头, ...
- POJ 1324 Holedox Moving (状压BFS)
POJ 1324 Holedox Moving (状压BFS) Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 18091 Acc ...
- POJ - 1324 Holedox Moving (状态压缩+BFS/A*)
题目链接 有一个n*m(1<=n,m<=20)的网格图,图中有k堵墙和有一条长度为L(L<=8)的蛇,蛇在移动的过程中不能碰到自己的身体.求蛇移动到点(1,1)所需的最小步数. 显然 ...
- poj 1324 状态压缩+bfs
http://poj.org/problem?id=1324 Holedox Moving Time Limit: 5000MS Memory Limit: 65536K Total Submis ...
- poj1324 Holedox Moving
Holedox Moving Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 16980 Accepted: 4039 D ...
- POJ.3279 Fliptile (搜索+二进制枚举+开关问题)
POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...
- POJ 1475 Pushing Boxes 搜索- 两重BFS
题目地址: http://poj.org/problem?id=1475 两重BFS就行了,第一重是搜索箱子,第二重搜索人能不能到达推箱子的地方. AC代码: #include <iostrea ...
- poj 3279 Fliptile (简单搜索)
Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16558 Accepted: 6056 Descrip ...
- poj 1198 hdu 1401 搜索+剪枝 Solitaire
写到一半才发现能够用双向搜索4层来写,但已经不愿意改了,干脆暴搜+剪枝水过去算了. 想到一个非常水的剪枝,h函数为 当前点到终点4个点的最短距离加起来除以2.由于最多一步走2格,然后在HDU上T了, ...
随机推荐
- 贴一个CMemDC 代码,这东西真不错噢,短小精悍,可谓极品
罗索客 发布于 2006-11-28 21:53 点击:3941次 来自: 原文: http://yuantao82.spaces.live.com/Blog/cns!8FC0A772D812A22 ...
- 【Error】JavaWeb: 严重: Failed to initialize end point associated with ProtocolHandler ["http-bio-8080"]
在MyEclipse中启动Tomcat时出现错误,错误信息例如以下: 严重: Failed to initialize end point associated with ProtocolHandle ...
- 注解框架---AndroidAnnotations
AndroidAnnotations是一个开源框架,旨在加快Android开发的效率.通过使用它开放出来的注解api,你差点儿可以使用在不论什么地方, 大大的降低了无关痛痒的代码量,让开发人员可以抽身 ...
- SRM 624 Building Heights DivI 解读
几乎相同的一标题.欲了解更多请参阅:http://community.topcoder.com/stat?c=problem_statement&pm=13211&rd=15857 思 ...
- Swift - 类的计算属性(使用get和set来间接获取/改变其他属性的值)
1,Swift中类可以使用计算属性,即使用get和set来间接获取/改变其他属性的值,代码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Calc ...
- 《转》VC++多线程编程
原地址:http://www.cnblogs.com/wxfasdic/archive/2010/09/23/1833522.html 留个纪念,不错的总结.十个例子清晰列举啦多线程编程的奥妙. V ...
- Java程序员们最常犯的10个错误(转)
1.将数组转化为列表 将数组转化为一个列表时,程序员们经常这样做: 1 List<String> list = Arrays.asList(arr); Arrays.asList(&quo ...
- OC对象创建过程
在利用OC开发应用程序中,须要大量创建对象,那么它的过程是什么呢? 比方:NSArray *array = [[NSArrayalloc] init]; 在说明之前,先把OC的Class描写叙述一下: ...
- Python基础 - 关键字
前言 与C一样,python也有自己的关键字,关键字有特殊的意义,不能作为普通的变量名类名等用途 关键字列表 以python2.7.5为例,有如下关键字: and del from not while ...
- Wix打包系列(一)如何使用wix制作安装程序
原文:Wix打包系列(一)如何使用wix制作安装程序 最近由于项目需要,需要给客户制作安装程序,一开始使用vs2005自带的打包工程来打包,但用了一段时间发现vs打包太死板,而且使用起来问题很多.收费 ...