CSP2013-12-5 I’m stuck!
思路:使用两次BFS。注意第二个条件是不可以从此方格移动到目标位置,可以将所有有向边翻转,然后转化为不可以从目标位置移动到此方格。所以要建两个图,这里使用邻接表存储。
- 第一次BFS,以S为出发点,标记所有从S能到达的点。对于方格u,若从方格u可移动一格到v(v!=’#’),则添加有向边(u,v)。注意:因为T不是出发点,所以u包括T。
- 第二次BFS,从T点出发,标记从T能到达的点。对于方格u,若从u移动一格可以到v(v!=’#’),则添加有向边(v,u)。注意:这里u不包括v。
最后时间复杂度为O(R*C)。
代码如下:
#include <iostream>
#include <vector>
#include <queue>
#include <string.h>
using namespace std;
#define S 'S'
#define T 'T'
#define CROSS '+'
#define HORIZONTAL '-'
#define VERTICAL '|'
#define DOWN '.'
#define BAN '#'
vector<int> node[2505]; //从S出发的邻接表
vector<int> Tnode[2505]; //从T出发
bool fromS[2505];
bool fromT[2505];
queue<int> q;
void fromS_BFS(int s)
{
while(!q.empty())
{
q.pop();
}
q.push(s);
fromS[s]=true;
int u,v;
while(!q.empty()){
u = q.front();
q.pop();
for(int i=0;i<node[u].size();i++){
v = node[u][i];
if(fromS[v]==false){
fromS[v]=true;
q.push(v);
}
}
}
}
void fromT_BFS(int t)
{
while(!q.empty())
{
q.pop();
}
q.push(t);
fromT[t]=true;
int u,v;
while(!q.empty()){
u = q.front();
q.pop();
for(int i=0;i<Tnode[u].size();i++){
v = Tnode[u][i];
if(fromT[v]==false){
fromT[v]=true;
q.push(v);
}
}
}
}
int main()
{
int R,C;
char ch[50][50];
memset(ch,0,sizeof(ch));
int pointS,pointT;
scanf("%d%d",&R,&C);
for(int i=0; i<R; i++)
{
scanf("%s",ch[i]);
}
for(int i=0; i<R; i++)
{
for(int j=0; j<C; j++)
{
node[i*C+j].clear(); //编码方式:ch中位置(i,j)编码为i*C+j
if(ch[i][j]==S){
pointS=i*C+j;
}else if(ch[i][j]==T){
pointT=i*C+j;
}
switch(ch[i][j])
{
case T:
if(i>0&&ch[i-1][j]!=BAN)
{
node[i*C+j].push_back((i-1)*C+j);
}
if(i<R-1&&ch[i+1][j]!=BAN)
{
node[i*C+j].push_back((i+1)*C+j);
}
if(j>0&&ch[i][j-1]!=BAN)
{
node[i*C+j].push_back(i*C+j-1);
}
if(j<C-1&&ch[i][j+1]!=BAN)
{
node[i*C+j].push_back(i*C+j+1);
}
break;
case S:
case CROSS:
if(i>0&&ch[i-1][j]!=BAN)
{
node[i*C+j].push_back((i-1)*C+j);
Tnode[(i-1)*C+j].push_back(i*C+j);
}
if(i<R-1&&ch[i+1][j]!=BAN)
{
node[i*C+j].push_back((i+1)*C+j);
Tnode[(i+1)*C+j].push_back(i*C+j);
}
if(j>0&&ch[i][j-1]!=BAN)
{
node[i*C+j].push_back(i*C+j-1);
Tnode[i*C+j-1].push_back(i*C+j);
}
if(j<C-1&&ch[i][j+1]!=BAN)
{
node[i*C+j].push_back(i*C+j+1);
Tnode[i*C+j+1].push_back(i*C+j);
}
break;
case HORIZONTAL:
if(j>0&&ch[i][j-1]!=BAN)
{
node[i*C+j].push_back(i*C+j-1);
Tnode[i*C+j-1].push_back(i*C+j);
}
if(j<C-1&&ch[i][j+1]!=BAN)
{
node[i*C+j].push_back(i*C+j+1);
Tnode[i*C+j+1].push_back(i*C+j);
}
break;
case VERTICAL:
if(i>0&&ch[i-1][j]!=BAN)
{
node[i*C+j].push_back((i-1)*C+j);
Tnode[(i-1)*C+j].push_back(i*C+j);
}
if(i<R-1&&ch[i+1][j]!=BAN)
{
node[i*C+j].push_back((i+1)*C+j);
Tnode[(i+1)*C+j].push_back(i*C+j);
}
break;
case DOWN:
if(i<R-1&&ch[i+1][j]!=BAN)
{
node[i*C+j].push_back((i+1)*C+j);
Tnode[(i+1)*C+j].push_back(i*C+j);
}
break;
default:
break;
}
}
}
memset(fromS,false,sizeof(fromS));
memset(fromT,false,sizeof(fromT));
fromS_BFS(pointS);
fromT_BFS(pointT);
int res=0;
for(int i=0;i<R*C;i++){
if(fromS[i]&&(!fromT[i])){
res++;
}
}
if(!fromS[pointT]){
printf("I'm stuck!");
}else{
printf("%d",res);
}
return 0;
}