题目链接
题意:
有两个人,同时从起点出发,问他们要走多少时间才能走完所有点(两个人的合计)。
思路:
这道题,我们如果是一条边的情况,那当然是简单的BFS,但是,对于两条边,我们得对BFS进行一下升华,对于这个BFS,我们得开一个四维+状压的数组,vis[i][x1][y1][x2][y2]:i是状压后的路径,表示走过这些点群,之后(x1, y1),(x2, y2)分别表示两个小人分别走到的点,然后每次走过的时候,就需要判断这个点能否能走,然后对该点的状态进行“异或(|)”处理。用一个队列去记录值的点,每次出队的时候判断是否这个出队的点已经遍历了所有的可走点,如果是的,就直接跳出子函数,因为,那必定是最先的那个点(BFS定理了)。
完整代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
const int maxN=4;
int dir[4][2]=
{
-1,0,
0,-1,
0,1,
1,0
};
int N, M, sx, sy, theEnd, ans;
bool within(int x, int y) //是否还在图内
{
return (x>=0 && y>=0 && x<N && y<M);
}
char mp[maxN][maxN];
bool vis[1<<16][maxN][maxN][maxN][maxN]; //是否遍历过这样的点
struct node
{
int getRode, x1, y1, x2, y2, t; //已经遍历过的路,(一号人)、(二号人)、已经花费时间
node(int a=0, int b=0, int c=0, int d=0, int f=0, int g=0)
{
getRode=a; x1=b; y1=c;
x2=d; y2=f; t=g;
}
};
void bfs(int x, int y)
{
memset(vis, false, sizeof(vis));
vis[1<<(x*M+y)][x][y][x][y]=true;
queue<node> Q;
Q.push(node(1<<(x*M+y), x, y, x, y, 0));
while(!Q.empty())
{
node u=Q.front();
Q.pop();
int id=u.getRode, x1=u.x1, y1=u.y1, x2=u.x2, y2=u.y2, t=u.t;
if(id==theEnd) { ans=t; return; }
for(int i=0; i<4; i++)
{
int xx1=x1+dir[i][0], yy1=y1+dir[i][1];
if(!within(xx1, yy1) || mp[xx1][yy1]=='X') continue;
for(int j=0; j<4; j++)
{
int xx2=x2+dir[j][0], yy2=y2+dir[j][1];
int newId=(id | (1<<(xx1*M+yy1)) ) | 1<<((xx2*M+yy2));
if(!within(xx2, yy2) || mp[xx2][yy2]=='X' || vis[newId][xx1][yy1][xx2][yy2]) continue;
vis[newId][xx1][yy1][xx2][yy2]=true;
Q.push(node(newId, xx1, yy1, xx2, yy2, t+1));
}
}
}
}
int main()
{
while(scanf("%d%d",&N,&M)!=EOF)
{
theEnd=0;
for(int i=0; i<N; i++)
{
scanf("%s",mp[i]);
for(int j=0; j<M; j++)
{
if(mp[i][j]=='O') { theEnd|=1<<(i*M+j); }
else if(mp[i][j]=='S') { sx=i; sy=j; theEnd|=1<<(i*M+j); }
}
}
bfs(sx, sy);
printf("%d\n", ans);
}
return 0;
}