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了, ...
随机推荐
- NET Core RC2
.NET Core RC2/RTM 明确了时间表 .NET Core 经过了将近2年的开发,去年12月份发布的RC1版本,明确来说那只是一个beta版本,自从RC1发布以来,看到github里的RC2 ...
- Delphi对WM_NCHITTEST消息的处理
前提:WM_NCHITTEST是很重要的,只要鼠标在活动,Windows无时无刻在发这个消息进行探测. ------------------------------------------------ ...
- (Google面试题)有四个线程1、2、3、4。线程1的功能就是输出1,线程2的功能就是输出2,以此类推.........现在有四个文件ABCD。初始都为空。
现要让四个文件呈如下格式: A:1 2 3 4 1 2.... B:2 3 4 1 2 3.... C:3 4 1 2 3 4.... D:4 1 2 3 4 1.... 请设计程序. 下面举例A,对 ...
- hdu 1063 Exponentiation 大数
Problem Description Problems involving the computation of exact values of very large magnitude and p ...
- Java提高篇(三二)-----List总结
前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点能够对List接口有了比較深的了解了.仅仅有通过归纳总结的知 ...
- 【ALearning】第二章 Androidproject知识介绍
本章介绍了主要的初步Androidproject成立了一个开发环境.为了Android意识的整体项目和理解.本章包含Android开发环境的搭建.第一Android工程Hello World与Andr ...
- 微信支付.net官方坑太多,我们来精简
原文:微信支付.net官方坑太多,我们来精简 微信支付官方坑太多,我们来精简 我把官方的代码,打包成了 an.wxapi.dll. 里面主要替换了下注释.呵呵.然后修改了几个地方. 修改一.Confi ...
- hdu1565+hdu1569(最大点权独立集)
传送门:hdu1565 方格取数(1) 传送门:hdu1569 方格取数(2) 定理:1. 最小点权覆盖集=最小割=最大流2. 最大点权独立集=总权-最小点权覆盖集 步骤: 1. 先染色,取一个点染白 ...
- hdu2444(判二分图+最大匹配)
传送门:The Accomodation of Students 题意:有n个学生,m对相互认识的,问能否分成两队,使得每对中没有相互认识的,如果可以求最大匹配,否则输出No. 分析:判断二分图用染色 ...
- svn简介与使用
本文简单介绍windows下svn服务器与客户端软件的简单应用. 其中,svn服务器用于储存和管理代码,相当与文本服务器的作用(多版本控制等功能),同时分配用户代码的访问与使用权限. 客户端软件 用于 ...