http://acm.hdu.edu.cn/showproblem.php?pid=2216

zjt和sara在同一个地图里,zjt要去寻找sara,zjt每移动一步sara就要往相反方向移动,如果他们相邻或者在同一个格子里就算相遇。

输出最少步数。注意zjt每次必须要有能移动的点才移动,否则不能移动,但是sara没有能移动的点的话可以呆着不动。

用结构体保存两个点和相应的步数作为一个状态,然后用哈希函数映射出每一个状态的的哈希值,放入set中,判重。

注意哈希函数的选取要确保不能重复。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set> using namespace std; struct PT
{
int x1,y1,x2,y2;
int step;
}; const int dir_x[]={,,,-};
const int dir_y[]={,-,,};
char mp[][];
int n,m; int ha(int a,int b,int c,int d)
{
int ret=a;
ret=ret*+b;
ret=ret*+c;
ret=ret*+d;
return ret;
} int main()
{
//freopen("a.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
int a=,b=,c=,d=;
for(int i=;i<n;i++) scanf("%s",mp[i]);
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(mp[i][j]=='Z')
{
a=i;b=j;
}
else if(mp[i][j]=='S')
{
c=i;d=j;
}
}
}
//printf("%d %d %d %d\n",a,b,c,d);
PT ac=(PT){a,b,c,d,}; queue<PT> q;
q.push(ac);
set<int> st;
st.insert(ha(a,b,c,d));
bool flag=false;
while(!q.empty())
{
PT u=q.front(),v; q.pop();
int x=abs(u.x1-u.x2)+abs(u.y1-u.y2);
if(x==||x==) //相邻或者相遇
{
printf("%d\n",u.step);
flag=true;
break;
}
for(int i=;i<;i++)
{
int X1=u.x1+dir_x[i],X2=u.x2-dir_x[i];
int Y1=u.y1+dir_y[i],Y2=u.y2-dir_y[i];
if(X1<||X1>=n||Y1<||Y1>=m||mp[X1][Y1]=='X')
{
continue;
}
if(X2<||X2>=n||Y2<||Y2>=m||mp[X2][Y2]=='X')
{
X2=X2+dir_x[i];Y2=Y2+dir_y[i];
}
// printf("%d %d %d %d\n",X1,Y1,X2,Y2);
int xx=u.step+;
int h=ha(X1,Y1,X2,Y2);
if(!st.count(h))
{
st.insert(h);
v=(PT){X1,Y1,X2,Y2,xx};
q.push(v);
}
}
}
if(!flag) cout<<"Bad Luck!\n";
}
return ;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set> using namespace std; struct point
{
int x1,y1,x2,y2;
int step;
}; const int dx[]={,,,-};
const int dy[]={,-,,};
char mp[][];
int n,m;
int used[][][][];
bool flag; void bfs(point s)
{
memset(used,,sizeof(used));
queue<point>que;
que.push(s);
used[s.x1][s.y1][s.x2][s.y2]=;
while(!que.empty())
{
point e=que.front(); que.pop();
int x=abs(e.x1-e.x2)+abs(e.y1-e.y2);
// printf("%d %d %d %d\n",e.x1,e.y1,e.x2,e.y2);
if(x==||x==)
{
flag=;
printf("%d\n",e.step);
return;
}
for(int i=;i<;i++)
{
s=e;
s.x1=e.x1+dx[i];s.y1=e.y1+dy[i];
if(s.x1<||s.x1>=n||s.y1<||s.y1>=m||mp[s.x1][s.y1]=='X') continue;
s.x2=e.x2-dx[i];s.y2=e.y2-dy[i];
if(s.x2<||s.x2>=n||s.y2<||s.y2>=m||mp[s.x2][s.y2]=='X')
{
s.x2+=dx[i];s.y2+=dy[i];
}
if(!used[s.x1][s.y1][s.x2][s.y2])
{
used[s.x1][s.y1][s.x2][s.y2]=;
s.step+=;
que.push(s);
}
}
}
}
int main()
{
//freopen("a.txt","r",stdin);
while(scanf("%d%d",&n,&m)!=EOF)
{
point s;
for(int i=;i<n;i++) scanf("%s",mp[i]);
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(mp[i][j]=='Z')
{
s.x1=i;s.y1=j;
}
else if(mp[i][j]=='S')
{
s.x2=i;s.y2=j;
}
}
}
s.step=;
flag=;
bfs(s);
if(!flag) printf("Bad Luck!\n");
}
return ;
}

http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1187

这道题以前看到没有思路去做,今天终于ac了。

跟上面一道题不同的是这里两个点是按照相同的指令移动,并且如果发出指令之后移动到了不合法的位置那么就忽略这条指令那么点应该返回到原来的位置,但是在还是需要记录这条指令  还有一个坑点是输出尽可能短的指令,如果长度相同输出字典序最小的指令,所以遍历四个方向是有先后顺序的,昨晚debug了一个小时才发现这个。

思路跟上面一样。

 #include <cstdio>
#include <cstring>
#include <queue>
#include <set>
#include <iostream>
using namespace std; struct point
{
int x1,y1,x2,y2;
string str;
}; char maze[][];
int n,m;
bool flag;
string go;
int dx[]={,,,-};
int dy[]={,-,,};
char dir[]={'D','L','R','U'}; //注意 顺序必须是这样 跟上面对应
int hash1(point s)
{
int cnt=s.x1;
cnt=cnt*+s.y1;
cnt=cnt*+s.x2;
cnt=cnt*+s.y2;
return cnt;
} void bfs(point s)
{
queue<point>que;
set<int>st;
que.push(s);
st.insert(hash1(s));
while(!que.empty())
{
point e=que.front(); que.pop();
//printf("%d %d %d %d\n",e.x1,e.y1,e.x2,e.y2);
if(flag&&e.str.size()>go.size()) break;
if(e.x1==e.x2&&e.y1==e.y2)
{
// cout<<e.str<<endl;
if(go.size()==)
{
go=e.str;
}
else if(go>e.str) go=e.str;
flag=true;
}
for(int i=;i<;++i)
{
s.x1=e.x1+dx[i],s.x2=e.x2+dx[i];
s.y1=e.y1+dy[i],s.y2=e.y2+dy[i];
// printf("%d %d %d %d \n",s.x1,s.y1,s.x2,s.y2);
if(s.x1<||s.x1>=n||s.y1<||s.y1>=m||maze[s.x1][s.y1]=='#')
{
s.x1-=dx[i];s.y1-=dy[i];
}
if(s.x2<||s.x2>=n||s.y2<||s.y2>=m||maze[s.x2][s.y2]=='#')
{
s.x2-=dx[i];s.y2-=dy[i];
}
// printf("%d %d %d %d\n",s.x1,s.y1,s.x2,s.y2);
s.str=e.str+dir[i];
int h=hash1(s);
if(!st.count(h))
{
st.insert(h);
que.push(s);
}
}
}
} int main()
{
// freopen("data.txt","r",stdin);
// freopen("b.txt","w",stdout);
while(~scanf("%d%d",&n,&m))
{
point s;
s.x1=,s.y1=,s.x2=,s.y2=,s.str="";
for(int i=;i<n;i++)
{
scanf("%s",maze[i]);
for(int j=;j<m;j++)
{
if(maze[i][j]=='*')
{
if(s.x1==&&s.y1==)
{
s.x1=i;s.y1=j;
}
else
{
s.x2=i;s.y2=j;
}
}
}
}
// printf("%d %d %d %d\n",s.x1,s.y1,s.x2,s.y2);
flag=;
go="";
bfs(s);
if(!flag) cout<<"Sorry"<<endl;
else cout<<go<<endl;
}
return ;
}

hdu - 2216 Game III && xtu 1187 Double Maze (两个点的普通bfs)的更多相关文章

  1. HDU 2216 Game III(BFS)

    Game III Problem Description Zjt and Sara will take part in a game, named Game III. Zjt and Sara wil ...

  2. hdu3713 Double Maze

    Problem Description Unlike single maze, double maze requires a common sequence of commands to solve ...

  3. hdu 1255 覆盖的面积(求覆盖至少两次以上的面积)

    了校赛,还有什么途径可以申请加入ACM校队?  覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  4. java 金额计算,商业计算 double不精确问题 BigDecimal,Double保留两位小数方法

    解决办法================== http://blog.javaxxz.com/?p=763 一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法 进行精 ...

  5. hdu 4630 查询[L,R]区间内任意两个数的最大公约数

    No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. java使double保留两位小数的多方法

    java使double保留两位小数的多方法 java保留两位小数 mport java.text.DecimalFormat; DecimalFormat df = new DecimalFormat ...

  7. HDU 4048 Zhuge Liang's Stone Sentinel Maze

    Zhuge Liang's Stone Sentinel Maze Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/327 ...

  8. HDU 3277Marriage Match III(二分+并查集+拆点+网络流之最大流)

    题目地址:HDU 3277 这题跟这题的上一版建图方法差点儿相同,仅仅只是须要拆点.这个点拆的也非常巧妙,既限制了流量,还仅仅限制了一部分,曾经一直以为拆点会所有限制,原来也能够用来分开限制,学习了. ...

  9. hdu 2216 bfs

    题目大意:两个东西朝相同方向移动Sample Input4 4XXXX.Z...XS.XXXX4 4XXXX.Z...X.SXXXX4 4XXXX.ZX..XS.XXXXSample Output11 ...

随机推荐

  1. 【BZOJ】【1015】 【JSOI2008】星球大战starwar

    并查集/时光倒流 删点维护连通块个数比较难处理,所以我们就逆序来做,先处理最后状态下有多少连通块,再依次加入被删的点,这样就变删点为加点,利用并查集即可维护连通块个数. /************** ...

  2. Java内存模型(JMM)

    参考: 1. http://www.tuicool.com/articles/UVzuQb

  3. .Net自带的委托类型—Func,Action 和 Predicate

    委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递. 与其他的类不同,委托类具有一个签名,并且它只能对与其签名匹配的方法进行引用. 一.自定义委托类型 1.语法结构:访问修 ...

  4. Leetcode#129 Sum Root to Leaf Numbers

    原题地址 二叉树的遍历 代码: vector<int> path; int sumNumbers(TreeNode *root) { if (!root) ; ; path.push_ba ...

  5. 7 天玩转 ASP.NET MVC — 第 6 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 欢迎来到第六天的 MVC 系列学习中.希望你在阅读此篇文章的时候,已经学习了前五天的内容,这也是第 ...

  6. 【面试题042】翻转单词顺序VS左旋转字符串

    [面试题042]翻转单词顺序VS左旋转字符串 题目一:     输入一个英文句子,反转句子中单词的顺序,但单词内字符的顺序不变.为简单起见,标点符号和普通字母一样处理.     例如输入字符串“I a ...

  7. poj 1704

    Georgia and Bob Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7233   Accepted: 2173 D ...

  8. DF学Mysql(二)——数据表的基本操作

    1.创建数据表 先使用“USE <数据库名>”指定在哪个数据库中操作 CREATE TABLE <表名> ( 字段1 数据类型 [列级别约束条件] [默认值], 字段2 数据类 ...

  9. Codeigniter整合Tank Auth权限类库的教程

    Codeigniter整合Tank Auth权限类库的教程一开始找了很多CodeIgniter的类库,觉得都不怎么样,后来干脆自己通过CI的钩子系统写了权限管理.但是还是不怎么满意,后来有人推荐tan ...

  10. hdu 4618(最大回文子矩阵)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4618 昨天多校的一道题,说多了都是泪啊,为了一道图论题,磨了那么久,结果是别的题都没看,没办法,补呗. ...