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.<br><br>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.<br><br>You havetocalculate the minimal time to approach Angel. (We can move only UP, DOWN,LEFTand RIGHT, to the neighbor grid within bound, of course.)<br>
Input
First line containstwointegers stand for N and M.<br><br>Then N lines follows, everylinehas M characters. "." stands for road, "a" standsforAngel, and "r" stands for each of Angel'sfriend.<br><br>Process to the end of the file.<br>
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." <br>
Sample Input
7 8
#.#####.
#.a#..r.
#..#x...
..#..#.#
#...##..
.#......
........
Sample Output
13
题目分析:
3这题坑了我好久,第一,这题的天使的朋友不止一个。第二,scanf的知识不足。
天使的朋友虽然不止一个,但是天使就一个,我们可以道着找,从天使找朋友。
接下来一篇时间超时的代码:
#include<bits/stdc++.h>
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<n&&y>=0&&y<m&&flag[x][y]==0)
{
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<tail);
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<n;i++)
{
scanf("%s",&mapp[i]);
for(j=0;j<m;j++)
{
if(mapp[i][j]=='#')
{flag[i][j]=1;}
}
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(mapp[i][j]=='a')
bfs(i,j);
if(ans)
cout<<ans<<endl;
else
cout<<"Poor ANGEL has to stay in the prison all hislife."<<endl;
}
return 0;
}
以为没使用队列的原因:
接下来队列的代码:
#include<bits/stdc++.h>
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<node>q;
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<n&&b.y>=0&&b.y<m)
{
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<n;i++)
{
scanf("%s",&mapp[i]);
for(j=0;j<m;j++)
{
if(mapp[i][j]=='#')
{vis[i][j]=1;}
}
}
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(mapp[i][j]=='a')
bfs(i,j);
if(ans)
cout<<ans<<endl;
else
cout<<"Poor ANGEL has to stay in the prison allhislife."<<endl;
}
return 0;
}
还是超时:
以为没用优先队列,上网学习优先队列:
#include<bits/stdc++.h>
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<node>q;
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<n&&b.y>=0&&b.y<m)
{
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<n;i++)
{
scanf("%s",&mapp[i]);
for(j=0;j<m;j++)
{
if(mapp[i][j]=='a')
{x=i;y=j;}
}
}
bfs(x,y);
if(ans)
cout<<ans<<endl;
else
cout<<"Poor ANGEL has to stay in the prison allhislife."<<endl;
}
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<bits/stdc++.h>
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<node>q;
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<n&&b.y>=0&&b.y<m)
{
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<n;i++)
{
scanf("%s",&mapp[i]);
for(j=0;j<m;j++)
{
if(mapp[i][j]=='a')
{x=i;y=j;}
}
}
bfs(x,y);
if(ans)
cout<<ans<<endl;
else
cout<<"Poor ANGEL has to stay in the prison allhislife."<<endl;
}
return 0;
}