Problem L
Time Limit : 2000/1000ms(Java/Other) Memory Limit :65536/32768K (Java/Other)
Total Submission(s) :23 Accepted Submission(s) : 6
Problem Description
Angel was caught bytheMOLIGPY! He was put in prison by Moligpy. The prison is described as a N *M(N, M <= 200) matrix. There are WALLs, ROADs, and GUARDs intheprison.
Angel's friends want to save Angel. Their taskis:approach Angel. We assume that "approach Angel" is to gettothe position where Angel stays. When there's a guard in the grid, we mustkillhim (or her?) to move into the grid. We assume that we moving up, down,right,left takes us 1 unit time, and killing a guard takes 1 unit time, too.And weare strong enough to kill all the guards.
You havetocalculate the minimal time to approach Angel. (We can move only UP, DOWN,LEFTand RIGHT, to the neighbor grid within bound, of course.)
Input
First line containstwointegers stand for N and M.
Then N lines follows, everylinehas M characters. "." stands for road, "a" standsforAngel, and "r" stands for each of Angel'sfriend.
Process to the end of the file.
Output
For each test case,yourprogram should output a single integer, standing for the minimal timeneeded.If such a number does no exist, you should output a line containing"PoorANGEL has to stay in the prison all his life."
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
题目分析:
3这题坑了我好久,第一,这题的天使的朋友不止一个。第二,scanf的知识不足。
天使的朋友虽然不止一个,但是天使就一个,我们可以道着找,从天使找朋友。
接下来一篇时间超时的代码:
#include
using namespace std;
int n,m,t,ans=0;
char mapp[205][205];
int flag[205][205]={0};
int dx[4]={-1,1,0,0},
dy[4]={0,0,1,-1};
int bfs(int x1,int y1)
{
int i,j,head=0,tail=1,x,y;
flag[x1][y1]=1;
intxx[100000],yy[100000],ti[100000];
xx[1]=x1;
yy[1]=y1;
ti[1]=0;
do
{
head++;
if(mapp[xx[head]][yy[head]]=='r')
{
ans=ti[head];
return 0;
}
else
for(i=0;i<4;i++)
{
x=xx[head]+dx[i];
y=yy[head]+dy[i];
if(x>=0&&x
{
if(mapp[x][y]=='.'||mapp[x][y]=='r')
{
tail++;
flag[x][y]=1;
xx[tail]=x;
yy[tail]=y;
ti[tail]=ti[head]+1;
}
elseif(mapp[x][y]=='x')
{
tail++;
flag[x][y]=1;
xx[tail]=x;
yy[tail]=y;
ti[tail]=ti[head]+2;
}
}
}
}while(head
return 0;
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m))
{
memset(flag,0,sizeof(flag));
int x,y;
for(i=0;i
{
scanf("%s",&mapp[i]);
for(j=0;j
{
if(mapp[i][j]=='#')
{flag[i][j]=1;}
}
}
for(i=0;i
for(j=0;j
if(mapp[i][j]=='a')
bfs(i,j);
if(ans)
cout<
else
cout<<"Poor ANGEL has to stay in the prison all hislife."<
}
return 0;
}
以为没使用队列的原因:
接下来队列的代码:
#include
using namespace std;
int n,m,ans=0;
char mapp[205][205];
int vis[205][205]={0};
int dx[4]={-1,1,0,0},
dy[4]={0,0,1,-1};
struct node
{
intx,y,step;
}a,b;
int bfs(int x1,int y1)
{
queue
a.x=x1;
a.y=y1;
vis[a.x][a.y]=1;
a.step=0;
q.push(a);
while(!q.empty())
{
a=q.front();
q.pop();
if(mapp[a.x][a.y]=='r')
{
ans=a.step;
return 0;
}
else
{for(inti=0;i<4;i++)
{
b.x=a.x+dx[i];
b.y=a.y+dy[i];
if(!vis[b.x][b.y]&&b.x>=0&&b.x
{
vis[b.x][b.y]=1;
if(mapp[b.x][b.y]=='.'||mapp[b.x][b.y]=='r')
b.step=a.step+1;
elseif(mapp[b.x][b.y]=='x')
b.step=a.step+2;
q.push(b);
}
}
}
}
return 0;
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m))
{
ans=0;
memset(vis,0,sizeof(vis));
int x,y;
for(i=0;i
{
scanf("%s",&mapp[i]);
for(j=0;j
{
if(mapp[i][j]=='#')
{vis[i][j]=1;}
}
}
for(i=0;i
for(j=0;j
if(mapp[i][j]=='a')
bfs(i,j);
if(ans)
cout<
else
cout<<"Poor ANGEL has to stay in the prison allhislife."<
}
return 0;
}
还是超时:
以为没用优先队列,上网学习优先队列:
#include
using namespace std;
int n,m,ans=0;
#define M 205
char mapp[M][M];
int vis[M][M]={0};
int dx[4]={0,0,1,-1},
dy[4]={1,-1,0,0};
struct node
{
intx,y,step;
friend booloperator< (constnode c,const node d) //第一次优先队列
{
returnc.step>d.step;
}
};
int bfs(int x1,int y1)
{
node a,b;
priority_queue
a.x=x1;
a.y=y1;
memset(vis,0,sizeof(vis));
vis[a.x][a.y]=1;
a.step=0;
q.push(a);
while(!q.empty())
{
a=q.top(); //小小不同
q.pop();
if(mapp[a.x][a.y]=='r')
{
ans=a.step;
return 0;
}
for(inti=0;i<4;i++)
{
b.x=a.x+dx[i];
b.y=a.y+dy[i];
if(mapp[b.x][b.y]!='#'&&!vis[b.x][b.y]&&b.x>=0&&b.x
{
vis[b.x][b.y]=1;
if(mapp[b.x][b.y]=='.'||mapp[b.x][b.y]=='r')
b.step=a.step+1;
else if(mapp[b.x][b.y]=='x')
b.step=a.step+2;
q.push(b);
}
}
}
return 0;
}
int main()
{
int i,j;
while(scanf("%d%d",&n,&m))
{
ans=0;
int x,y;
for(i=0;i
{
scanf("%s",&mapp[i]);
for(j=0;j
{
if(mapp[i][j]=='a')
{x=i;y=j;}
}
}
bfs(x,y);
if(ans)
cout<
else
cout<<"Poor ANGEL has to stay in the prison allhislife."<
}
return 0;
}
结果还是超时:
弄了好久,才知道是循环输入scanf的问题:
这个要从scanf函数的返回值说起。
比如scanf("%d", &n);有如下情况:
1. 当输入为一个整数时,读取到n,scanf返回值是1(表示成功读取了一个数),ok,继续执行
2. 当输入为EOF(通常切的题目有多组数据,会使用EOF表示输入结束),这时,没有读取输入到n,scanf返回值是-1,所以您的代码==1就不成立,所以会跳出循环。而如果是while(scanf("%d",&n))的话,即等价于while(-1),显然还会继续循环,所以超时。
所以可以有以下用法:
1. while(scanf("%d", &n) == 1)
2. while(scanf("%d", &n) != EOF)
3. while(~scanf("%d", &n)) 当输入为EOF时,-1求反为0哦,所以也可以。
接下来优先队列AC代码:
#include
using namespace std;
int n,m,ans=0;
#define M 205
char mapp[M][M];
int vis[M][M]={0};
int dx[4]={0,0,1,-1},
dy[4]={1,-1,0,0};
struct node
{
intx,y,step;
friend booloperator< (constnode c,const node d) //第一次优先队列
{
returnc.step>d.step;
}
};
int bfs(int x1,int y1)
{
node a,b;
priority_queue
a.x=x1;
a.y=y1;
memset(vis,0,sizeof(vis));
vis[a.x][a.y]=1;
a.step=0;
q.push(a);
while(!q.empty())
{
a=q.top(); //小小不同
q.pop();
if(mapp[a.x][a.y]=='r')
{
ans=a.step;
return 0;
}
for(inti=0;i<4;i++)
{
b.x=a.x+dx[i];
b.y=a.y+dy[i];
if(mapp[b.x][b.y]!='#'&&!vis[b.x][b.y]&&b.x>=0&&b.x
{
vis[b.x][b.y]=1;
if(mapp[b.x][b.y]=='.'||mapp[b.x][b.y]=='r')
b.step=a.step+1;
elseif(mapp[b.x][b.y]=='x')
b.step=a.step+2;
q.push(b);
}
}
}
return 0;
}
int main()
{
int i,j;
scanf("%d%d",&n,&m)!=EOF
{
ans=0;
int x,y;
for(i=0;i
{
scanf("%s",&mapp[i]);
for(j=0;j
{
if(mapp[i][j]=='a')
{x=i;y=j;}
}
}
bfs(x,y);
if(ans)
cout<
else
cout<<"Poor ANGEL has to stay in the prison allhislife."<
}
return 0;
}