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 ...
随机推荐
- java之File
1.文件创建.重命名.删除 code: package com.test; import java.io.File; import java.io.IOException; public class ...
- python中os模块常用方法
#!/usr/bin/python## os module test import os print 'os.name: ', os.nameprint 'os.getcwd(): ', os.get ...
- kendo ui中grid页面参数问题
kendo ui 中grid 算是最长用的控件之一,当使用分页效果时,我们要传递分页参数与自己定义的参数如: var dataSource = new kendo.data.DataSource({ ...
- [WebStrom] Cannot detect file change to trigger webpack re-compile
Working with editors/IDEs supporting “safe write” Note that many editors support “safe write” featur ...
- Java学习笔记——JDBC之与数据库MySQL的连接以及增删改查等操作
必须的准备工作 一.MySQL的安装.可以参考博文: http://blog.csdn.net/jueblog/article/details/9499245 二.下载 jdbc 驱动.可以从在官网上 ...
- python - 执行父类中的方法
执行父类中的方法: class C1: def f1(self): print('c1.f1') return 123 class C2(C1): def f1(self): #主动执行父类的f1方法 ...
- CodeSmith使用总结--创建一个基础模板
问:为什么要用CodeSmith? 答曰:因为我懒的写. Codesmith是一款非常不错的懒人工具,我也经常会用到,因为它在“重复代码”方面能够节省我们很多时间,并且解除了我们重复繁琐并且乏味的“码 ...
- (转)C#之玩转反射
前言 之所以要写这篇关于C#反射的随笔,起因有两个: 第一个是自己开发的网站需要用到 其次就是没看到这方面比较好的文章. 所以下定决心自己写一篇,废话不多说开始进入正题. 前期准备 在VS20 ...
- web并发访问的问题
一般的webapplication,可能会遇到这样的问题,你可以这样模拟:用浏览器开一个窗口,选中一条记录,编辑之,但是先不要保存,新开一个浏览器窗口,找到这条记录,删除之,然后再回到第一个窗口点击保 ...
- iOS~~MD5加密
// 一般加密 +(NSString *)md5String:(NSString *)str { const char *password=[str UTF8String]; unsigned cha ...