Poj2946-The Warehouse(bfs+哈希)
题目我就不粘贴了。。。
题意:给出地图,最大8*8,出口用'E'表示,空地用'.'表示,数字表示此处有多少个箱子,主人公的起点应该是在有箱子的地方,他可以朝四个方向移动,但是只有两种方式
一种是他移动到的位置也是有箱子的地方,另一种是空地,此时他可以把他所处位置的箱子全部推倒,朝那个方向铺成一条线,相当于每个地方一个箱子,但是所铺的位置原来
必须是 '.',否则是不能移动。问主人公最少需要多少步才能到达出口。不能达到输出Impossible.
解析:这题难在保存状态,而不在搜索的过程,最多有64个格子,相当于64个数,那么我们可以考虑用哈希将这么多数哈希成一个值,如何哈希呢?我是给每个数乘上一个系数,
比如第一个数乘上1,第二个数乘上1+131,第3个数乘上1+131+131,依此下去,然后模上一个数,用链表保存哈希值和对应的结构体下标,因为可能会出现两种不同的
状态哈希成同一个值,所以保存结构体下标是为了比较整个状态(这种需要整体比较的情况很少),其实整个搜索的状态并不是很多,用用哈希,细点心基本就可以过了。
代码
#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+;
const double eps=1e-;
const int mod=;
const int maxn=;
int N,bex,bey;
int dx[]={-,,,},dy[]={,-,,};
bool in(int x,int y){ return x>=&&x<N&&y>=&&y<N; }
structnode
{
char S[][]; //结构体保存整个图和人的坐标
int x,y;
}nod[maxn];
structHash
{
int v,nid,next; //保存哈希值,结构体下标,以及next指针
}ha[mod+maxn];
int f,r,hash_id; //队首队尾指针
int GetHash(char S[][])
{
int ret=,k=;
for(int i=;i<N;i++)
for(int j=;j<N;j++) //得到哈希值
{
if(S[i][j]>=''&&S[i][j]<='') ret+=(S[i][j]-'')*k;
else ret+=*k;
k+=;
}
return ret;
}
bool Same(int a,int b) //整个状态比较
{
if(nod[a].x!=nod[b].x) return false;
if(nod[a].y!=nod[b].y) return false;
for(int i=;i<N;i++)
for(int j=;j<N;j++) if(nod[a].S[i][j]!=nod[b].S[i][j]) return false;
return true;
}
bool Insert_Hash(int v,int nid)
{
int a=v%mod;
int p=ha[a].next;
while(p!=-)
{
if(ha[p].v==v&&Same(ha[p].nid,nid)) return false; //出现相同的状态
p=ha[p].next;
}
p=++hash_id; //增加节点
ha[p].v=v; ha[p].nid=nid;
ha[p].next=ha[a].next; ha[a].next=p; //前插法
return true;
}
bool check(node& t,int x,int y,int k) //检查能都铺
{ int step=t.S[x][y]-'';
if(step==) return false;
t.S[x][y]='.';
while(step--)
{
x+=dx[k];
y+=dy[k];
if(!in(x,y)||t.S[x][y]!='.') return false; //越界不行,不是'.'也不行
t.S[x][y]='';
}
return true;
}
void Print(node& t)
{
printf("%d %d\n",t.x,t.y);
for(int i=;i<N;i++) printf("%s\n",t.S[i]);
puts("=========");
}
bool AddNode(node& t,int k)
{
int x=t.x,y=t.y;
int nx=x+dx[k],ny=y+dy[k];
if(!in(nx,ny)) return false;
if(t.S[nx][ny]=='E') return true; //到达出口
node& tt=nod[r];
tt=t; tt.x=nx; tt.y=ny;
if(t.S[nx][ny]=='.')
{
if(!check(tt,x,y,k)) return false;
}
int a=GetHash(tt.S);
if(Insert_Hash(a,r)) r++; //添加到队尾
//Print(tt);
return false;
}
bool bfs()
{
int en=r;
while(f<en)
{
node& t=nod[f++];
for(int i=;i<;i++) if(AddNode(t,i)) return true;
}
return false;
}
int solve()
{
if(nod[].S[bex][bey]=='E') return ;
if(nod[].S[bex][bey]=='.') return -;
for(int i=;i<mod;i++) ha[i].next=-;
hash_id=mod-;
f=,r=;
int step=;
while(f<r)
{
step++;
if(bfs()) return step;
}
return -;
}
int main()
{
while(scanf("%d%d%d",&N,&bex,&bey)!=EOF)
{
if(!N&&!bex&&!bey) break;
nod[].x=--bex; nod[].y=--bey;
for(int i=;i<N;i++) scanf("%s",nod[].S[i]);
int ans=solve();
if(ans==-) printf("Impossible.\n");
else printf("%d\n",ans);
}
return ;
}
Poj2946-The Warehouse(bfs+哈希)的更多相关文章
- UVA 10651 Pebble Solitaire(bfs + 哈希判重(记忆化搜索?))
Problem A Pebble Solitaire Input: standard input Output: standard output Time Limit: 1 second Pebble ...
- poj 2432 Around the world bfs+哈希
由于每个点的状态包含走过来的距离,所以要存二维的状态,但是状态总量太多,所以可以用哈希来搞. 那么就是bfs最短路,哈希记录状态了. #include <iostream> #includ ...
- hdu1067-Gap(bfs+哈希)
Let's play a card game called Gap. You have 28 cards labeled with two-digit numbers. The first digit ...
- 【算法】BFS+哈希解决八数码问题
15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...
- POJ-3131-Cubic Eight-Puzzle(双向BFS+哈希)
Description Let's play a puzzle using eight cubes placed on a 3 × 3 board leaving one empty square. ...
- codevs1004四子连棋[BFS 哈希]
1004 四子连棋 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在一个4*4的棋盘上摆放了14颗棋子,其中有7颗 ...
- HDU 1043 Eight 【经典八数码输出路径/BFS/A*/康托展开】
本题有写法好几个写法,但主要思路是BFS: No.1 采用双向宽搜,分别从起始态和结束态进行宽搜,暴力判重.如果只进行单向会超时. No.2 采用hash进行判重,宽搜采用单向就可以AC. No.3 ...
- LeetCode_算法及数据结构覆盖统计
[输入]共计151道题的算法&数据结构基础数据 (见附录A) [输出-算法]其中有算法记录的共计 97道 ,统计后 结果如下 top3(递归,动态规划,回溯) 递归 动态规划 回溯 BFS ...
- HDU 1067 Gap
HDU 1067 Gap Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) P ...
随机推荐
- inconvertible types; cannot cast 'android.supoort.v4.app.Fragment' to 'com.example.sevenun.littledemo.fragment.NewsTitleFragment'
inconvertible types; cannot cast 'android.supoort.v4.app.Fragment' to 'com.example.sevenun.littledem ...
- 编写高质量代码改善python程序91个建议学习01
编写高质量代码改善python程序91个建议学习 第一章 建议1:理解pythonic的相关概念 狭隘的理解:它是高级动态的脚本编程语言,拥有很多强大的库,是解释从上往下执行的 特点: 美胜丑,显胜隐 ...
- flash与字符串:字符串与属性
有时候,我们想通过设置一个DisplayObject 类是属性值,只是需要通过点来引用即可.有时候,通过字符串也可以引用显示对象里面的属性值. 下面举个例子 . ...
- 【InversionCount 逆序对数 + MergeSort】
Definition of Inversion: Let (A[0], A[1] ... A[n], n <= 50) be a sequence of n numbers. If i < ...
- .Net的PDF转图片
用的是破解版的 O2S.Components.PDFRender4NET.dll 插件, 简单引用即可 public static class PdfToImage { , , ) { try { / ...
- transition过渡的趣玩
本例中将三张图(来自网络)进行堆叠,鼠标悬停触发.附有源代码
- MySQL的一些语法总结
初学MySQL,今天遇到了一个问题,然后汇总了一下MySQL的一些语法 1. date和datetime类型是不同的 date只记录日期(包括年月日),datetime记录日期和时间(包括年月日时分秒 ...
- 返回ipv 地址
//返回ipv 地址 public static string GetIP4Address() { string IP4Address = String.Empty; foreach (IPAddre ...
- JS中的for和for in循环
1.for循环通常用来遍历数组或类数组对象 模式1:长度缓存 for(var i=0,max=arr.length;i<max;i++){ //your code } 模式2:逐减,与零比较比与 ...
- Installation error: INSTALL_CANCELED_BY_USER
这个错误,从字面上理解,就是已经安装的时候被用户取消了. 我出现这个错误的时候,是手机连接在电脑上的. 经过网上搜索,确认这是安装apk到手机时,被手机取消了安装操作. 1. 确保手机处于开发者模式. ...