http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1649
这道题目真的纠结很久了,从一开始的dfs做法到bfs。dfs做的到是顺利,但是zoj上过不了,hdoj上倒是过了,数据弱。
题意上理解也有问题,看到hdoj上的discuss版,是关于a的问题。确实,r有多个。但我看到很多做法是只确定一个r的值并且这种做法也ok.但这样应该不可以。
bfs做法有2种,一种是用数组模拟队列,第二种是直接队列做。我比较喜欢用队列,感觉直观很多。
C++里的队列基本做法:
queue用法
1. back 返回队列最后一个元素引用
2. empty 判断队列是否为空
3. front 获得队列最前面一个元素引用
4. push 在队列尾添加一个数据
5. pop 删除队列头的一个数据
6. size 队列中元素个数
本题适合用优先队列
Priority_queue 用法
Priority_queue<type>Q //创建一个类型为type的队列Q
Bool empty() //判空
push(t) // 将t压入队列
pop() // 非空情况下删除队列中优先级最高地情况
Top() // 返回队列中优先级最高的元素。
http://support.microsoft.com/kb/157622/zh-cn
发下dfs我写的,但bfs是参考别人的有两种:普通队列和优先队列。看到小媛的还是觉得她比较靠谱:把符合条件的r都压入队列。。。
#include <stdio.h>
char a[210][210];
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int N,M,flag,count,endx,endy;
int main()
{
void dfs(int x,int y,int temp);
int startx,starty;
int i,j;
while(scanf("%d%d",&N,&M)!=EOF)
{
count=9999;
flag=0;
for(i=0;i<N+2;i++)
{
a[i][0]='#';
a[i][M+1]='#';
}
for(i=0;i<M+2;i++)
{
a[0][i]='#';
a[N+1][i]='#';
}
for(i=1;i<=N;i++)
{
getchar();
for(j=1;j<=M;j++)
{
scanf("%c",&a[i][j]);
if(a[i][j]=='a')
{
startx=i;
starty=j;
}
if(a[i][j]=='r')
{
endx=i;
endy=j;
}
}
}
a[startx][starty]='#';
dfs(startx,starty,0);
if(flag)
printf("%d\n",count);
else
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
return 0;
}
void dfs(int x,int y,int temp)
{
int i,temp_x,temp_y;
if(x==endx&&y==endy)//问题出在这里,之前在dfs函数之前就把a[x][y]覆盖成了'#',所以改步永远都无法做到。
{
flag=1;
if(count>temp)
count=temp;
return;
}
for(i=0;i<4;i++)
{
temp_x=x+dir[i][0];
temp_y=y+dir[i][1];
if(a[temp_x][temp_y]!='#')
{
if(a[temp_x][temp_y]=='x')
{
a[temp_x][temp_y]='#';
dfs(temp_x,temp_y,temp+2);
a[temp_x][temp_y]='x';
}
else
{
a[temp_x][temp_y]='#';
dfs(temp_x,temp_y,temp+1);
a[temp_x][temp_y]='.';
}
}
}
}
bfs:
优先队列的:http://blog.csdn.net/zxy_snow/article/details/6176139
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string.h>
#include <queue>
#define MAX 201
using namespace std;
typedef struct ANG
{
int t;
int x,y;
}ANG;
char map[MAX][MAX];
int vis[MAX][MAX];
int n,m;
int dir[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
priority_queue<ANG> q;
bool operator<(ANG a, ANG b)//优先队列
{
return a.t > b.t;
}
int BFS()
{
ANG tmp;
int i,a,b,aa,bb,t;
while( !q.empty() )
{
tmp = q.top();
q.pop();
a = tmp.x;
b = tmp.y;
t = tmp.t;
for(i=0; i<4; i++)
{
aa = a + dir[i][0];
bb = b + dir[i][1];
if( aa >= 0 && aa < n && bb >=0 && b < m && map[aa][bb] != '#' && !vis[aa][bb] )
{
vis[aa][bb] = 1;
if( map[aa][bb] == 'a' )
return t+1;
if( map[aa][bb] == '.' )
{
tmp.t = t + 1;
tmp.x = aa;
tmp.y = bb;
q.push(tmp);
}
if( map[aa][bb] == 'x')
{
tmp.t = t + 2;
tmp.x = aa;
tmp.y = bb;
q.push(tmp);
}
}
}
}
return -1;
}
int main()
{
int i,k,ans;
ANG tmp;
while(~scanf("%d%d",&n,&m))
{
memset(map,0,sizeof(map));
for(i=0; i<n; i++)
scanf("%s",map[i]);
while(!q.empty())
q.pop();
memset(vis,0,sizeof(vis));
for(i=0; i<n; i++)
for(k=0; k<m; k++)
if( map[i][k] == 'r' )
{
map[i][k] = '.';
tmp.x = i;
tmp.y = k;
tmp.t = 0;
q.push(tmp);//原来是这样的每次把符合条件的全部都入队...
vis[i][k] = 1;
}
ans=BFS();
if(ans !=-1)
printf("%d\n",ans);
else
printf("Poor ANGEL has to stay in the prison all his life.\n");
}
return 0;
}
不用优先队列的话,遇到'x'不能直接t+2压入队列。学习了STL里的队列和优先队列的做法^_^