http://acm.hdu.edu.cn/showproblem.php?pid=2653
#include<iostream>
#include<queue>
using namespace std;
#define N 81
bool h[N][N][N];
int dir[4][2]={-1,0,0,-1,1,0,0,1};
struct node{
int x,y;
int step;
int pow;
bool friend operator< (const node &a,const node& b){
if(a.step==b.step)
return a.pow<b.pow;
return a.step>b.step;
}
};
char map[N][N];
int n,m,T,P;
int fx,fy;
bool judge(node p){
if(p.x>=0&&p.x<n&&p.y>=0&&p.y<m&&map[p.x][p.y]!='#')
return true;
return false;
}
void bfs(){
priority_queue<node> q;
node temp,p;
p.x=fx;p.y=fy;
p.step=0;
p.pow=P;
memset(h,0,sizeof(h));
q.push(p);
h[fx][fy][P]=1;
while(!q.empty()){
temp=q.top();
q.pop();
if(map[temp.x][temp.y]=='L'){
if(temp.step<=T){
printf("Yes, Yifenfei will kill Lemon at %d sec.\n",temp.step);
return;
}
break;
}
//fly//
if(temp.pow>0){
for(int i=0;i<4;i++){
p=temp;
p.x+=dir[i][0];
p.y+=dir[i][1];
p.step++;
p.pow--;
if(judge(p)&&!h[p.x][p.y][p.pow]){
h[p.x][p.y][p.pow]=1;
q.push(p);
}
}
}
//work//
if(map[temp.x][temp.y]=='@')
continue;
for(int i=0;i<4;i++){
p=temp;
p.x+=dir[i][0];
p.y+=dir[i][1];
p.step+=2;
if(judge(p)&&!h[p.x][p.y][p.pow]){
if(map[p.x][p.y]=='@') continue;
h[p.x][p.y][p.pow]=1;
q.push(p);
}
}
}
printf("Poor Yifenfei, he has to wait another ten thousand years.\n");
}
int main(void){
int k=1;
while(~scanf("%d%d%d%d",&n,&m,&T,&P)){
for(int i=0;i<n;i++){
scanf("%s",map[i]);
for(int j=0;j<m;j++)
if(map[i][j]=='Y'){
fx=i;
fy=j;
}
}
printf("Case %d:\n",k++);
bfs();
}
}
太经典啦!刚开始还想着要是走到的是‘@’,那不是得再从此点往四周扩展,但是扩展的途中又会遇到'@',此时不是又得继续扩展吗?好麻烦!!> . <
无奈,百度了一下,看了AC大大的,恍然大悟啊!完全不用扩展下去的,每次分为fly 或者 work 两种,fly 没什么特别的要求,但是work 的话有两个,一个如果当前点是'@'的话不能work (!!!就是这里经典啊!!),还有不要忘记如果扩展出去的是'@'的话,那也是不行的,因为你是要走过去的,'@'要求是fly才能到达的。。。。主要是思考如果当前点是'@'的话,如何扩展,知道方法了自然觉得简单,但是自己思考的时候就往复杂的想了,比如想着不能把‘@’这个点入队,应该由这个点扩展下去的点入队,这样就很麻烦了!