【POJ】2312-Battle City(优化的广度搜索BFS)
使用了不完全的对拍来查错;
【题目链接】http://poj.org/problem?id=2312
答题思路
还是bfs,但是不同步,遇到’B’是两步。第一次写错主要是因为在遇到B时把B变成Y,但是搜索的路径有很多条,第一次变了后面的其他路径过来就只需要一步。所以重点在于遇到B走两步,但也不能一下走两步,一下走两步就不能用普通队列了。
具体操作写在注释里了。
错误代码
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<math.h>
#include<limits.h>
#include<stack>
#include<queue>
#define LL long long
using namespace std;
int m,n,ans;
int i,j;
char a[305][305];
int vis[305][305];
struct node
{
int x,y,step;
};
int mx[4]={1,-1,0,0};
int my[4]={0,0,1,-1};
queue <node> q;
void bfs()
{//printf(" mm ");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(a[i][j]=='Y')
{//printf("i=%d,j=%d",i,j);
vis[i][j]=1;
break;
}
}if(vis[i][j]==1)
break;
}//printf(" vis[%d][%d]=%d ",i,j,vis[i][j]);
if(vis[i][j]==0)
{//printf("ttxx");
return;
}
node st,f,e;
st.x=i;
st.y=j;
st.step=0;
q.push(st);
while(!q.empty())
{//printf("A");
f=q.front();
q.pop();
for(i=0;i<4;i++)
{//printf("C");
e=f;
if(e.x+mx[i]>=0&&e.x+mx[i]<m&&e.y+my[i]>=0&&e.y+my[i]<n&&vis[e.x+mx[i]][e.y+my[i]]==0)
{
e.x+=mx[i];
e.y+=my[i];
if(a[e.x][e.y]=='T')
{//printf("T");
e.step=f.step+1;
ans=e.step;
return;
}
else if(a[e.x][e.y]=='B')//错误在此,遇到1个B直接加一步并将其变为E,从其他路径到此的步数就少了1;
{//printf("B");
f.step++;
a[e.x][e.y]='E';
q.push(f);
f.step--;
}
else if(a[e.x][e.y]=='E')
{//printf("E");
e.step=f.step+1;
vis[e.x][e.y]=1;
q.push(e);
}
}
}
}
}
int main()
{
while(scanf("%d%d",&m,&n)!=EOF&&!(m==0&&n==0))
{
ans=-1;
memset(a,'0',sizeof(a));
for(int i=0;i<m;i++)
scanf("%s",a[i]);
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
bfs();
printf("%d\n",ans);
}
return 0;
}
修改后代码
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<math.h>
#include<limits.h>
#include<stack>
#include<queue>
#define LL long long
using namespace std;
int m,n,ans;
int i,j;
char a[305][305];
int vis[305][305];
struct node
{
int x;
int y;
int step;
};
int mx[4]={-1,1,0,0};
int my[4]={0,0,-1,1};
queue <node> q;
void bfs()
{//printf(" mm ");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(a[i][j]=='Y')
{//printf("i=%d,j=%d",i,j);
vis[i][j]=1;
break;
}
}if(vis[i][j]==1)
break;
}//printf(" vis[%d][%d]=%d ",i,j,vis[i][j]);
if(vis[i][j]==0)
{//printf("ttxx");
return;
}
node st,f,e;
st.x=i;
st.y=j;
st.step=0;
q.push(st);
while(!q.empty())
{//printf("A");
f=q.front();
q.pop();
if(vis[f.x][f.y]==1&&a[f.x][f.y]=='B')//(这是第二次检验这个点)发现这个点是'B',步数+1;
{
vis[f.x][f.y]=2;
f.step++;
q.push(f);
continue;
}
for(i=0;i<4;i++)
{//printf("C");
e=f;
if(e.x+mx[i]>=0&&e.x+mx[i]<m&&e.y+my[i]>=0&&e.y+my[i]<n&&vis[e.x+mx[i]][e.y+my[i]]==0)
{
e.x+=mx[i];
e.y+=my[i];
if(a[e.x][e.y]=='T')
{//printf("T");
e.step=f.step+1;
ans=e.step;
return;
}
else if(a[e.x][e.y]=='B')//第一次搜到'B',步数+1,先走过去
{//printf("B");
e.step++;
vis[e.x][e.y]=1;
q.push(e);
}
else if(a[e.x][e.y]=='E')
{//printf("E");
e.step=f.step+1;
vis[e.x][e.y]=1;
q.push(e);
}
}
}
}
return;
}
int main()
{
//freopen("C:\\Users\\阿烬\\Desktop\\acm\\duipai\\data.txt","r",stdin);
//freopen("C:\\Users\\阿烬\\Desktop\\acm\\duipai\\out2.txt","w",stdout);
//用到对拍;
while(scanf("%d%d",&m,&n)!=EOF&&!(m==0&&n==0))
{
ans=-1;
memset(a,'0',sizeof(a));
for(int i=0;i<m;i++)
scanf("%s",a[i]);
while(!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
bfs();
printf("%d\n",ans);
}
return 0;
}
用来生成数据的代码
#include<cstring>
#include<ctime>
#include<cstdlib>
int a[305][305];
char b[305][305];
int main(void)
{
freopen("C:\\Users\\阿烬\\Desktop\\acm\\duipai\\data.txt","w",stdout);
int x,y;
while(scanf("%d%d",&x,&y)!=EOF&&!(x==0&&y==0))
{
srand(time(NULL));
printf("%d %d\n",x,y);
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
{
a[i][j]=rand()%283;
}
}
int xx[2],yy[2];
xx[1]=rand()%x;
yy[1]=rand()%y;
a[xx[1]][yy[1]]=300;
while(1)
{
xx[0]=rand()%x;
yy[0]=rand()%y;
if(a[xx[0]][yy[0]]!=300)
{
a[xx[0]][yy[0]]=310;
break;
}
}
for(int i=0;i<x;i++)
{
for(int j=0;j<y;j++)
{
if(a[i][j]<130)
b[i][j]='B';
else if(a[i][j]<=280)
b[i][j]='E';
else if(a[i][j]==281)
b[i][j]='S';
else if(a[i][j]==282)
b[i][j]='R';
else if(a[i][j]==300)
b[i][j]='Y';
else if(a[i][j]==310)
b[i][j]='T';
printf("%c",b[i][j]);//数据不能完全随机,那样答案就一直是-1了;
}
printf("\n");
}
}
printf("0 0");
return 0;
}