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 ;
}