C - Curling 2.0
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Description
On Planet MM-21, after their Olympic games this year, curling is getting popular. But the rules are somewhat different from ours. The game is played on an ice game board on which a square mesh is marked. They use only a single stone. The purpose of the game is to lead the stone from the start to the goal with the minimum number of moves.
#include<stdio.h>
#include<string.h>
int map[25][25];
int drx[4]={0,1,0,-1},dry[4]={1,0,-1,0};
int w,h,x1,y1,min;
int DFS(int x,int y, int step);
int main()
{
while(scanf("%d%d",&w,&h)&& w!=0)
{
min=5000;
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++){
scanf("%d",&map[i][j]);
if(map[i][j]==2){
x1=i;y1=j;}
}
DFS(x1,y1,0);
printf("%d\n",min>10?-1:min);
}
return 0;
}
int DFS(int x,int y, int step)
{
int nx,ny;
if(step>10)return 0; //把这个放前面会让你节约至少一半的时间;
for(int i=0;i<4;i++){
nx=x+drx[i];ny=y+dry[i];
if(nx>0 && nx<=h && ny>0 && ny<=w && map[nx][ny]!=1){//判断初始方向是否能走;
do{ //直线行走;
if(map[nx][ny]==3){ if(step+1<min) min=step+1; return 0;}
nx=nx+drx[i];ny=ny+dry[i];
}while(nx>0 && nx<=h && ny>0 && ny<=w && map[nx][ny]!=1);
}
else continue; //不能走换方向;
if(nx<=0 || nx>h || ny<=0 || ny>w) continue;//出界了舍弃;
map[nx][ny]=0;
DFS(nx-drx[i],ny-dry[i],step+1); //注意若写成step++,后面相应的要写好step--;做好回溯嘛~;
map[nx][ny]=1;
}
return 0;
}
注意:①用 if 判断时,若有多个判断少用else 多用do-while,continue,break 会使代码看起来更清晰。
②要么用回溯step++,step--,要么多加一个step变量(vis[]=1,vis[]=0 必须的)。
但是为什么用BFS做 runtime error 了!!真是想不明白 = =!
#include<stdio.h>
#include<string.h>
int w,h,z1;
int map[25*25][25*25],q[25*25],dis[25*25]; //map[树结点序数][一维坐标值]=树结点状态(0,1,2 or 3);
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int B_search()
{
memset(q,0,sizeof(q));
memset(dis,0,sizeof(dis));
int front=0,rear=1,
z=z1,x,y,nx,ny,nz;
q[0]=z,dis[0]=0;
while(front<rear){
z=q[front];
x=z/w;y=z%w;
for(int i=0;i<4;i++){
nx=x+dx[i],ny=y+dy[i],nz=nx*w+ny;
if(map[front][nz]==3) return 1; //第一步就找到了出口;
if( nx<=h && nx>0 && ny<=w && ny>0 && map[front][nz]!=1){ //初方向判定;
do{
if(map[front][nz]==3) { //到了出口;
if(dis[front]+1>10)
return -1;
else
return dis[front]+1;}
nx=nx+dx[i];ny=ny+dy[i];nz=nx*w+ny; //先走后判,走直线;
}while(nx<=h && nx>0 && ny<=w && ny>0 && map[front][nz]!=1);//未出界也未碰到格挡物继续往前走;
}
else continue;
if(nx>h || nx<=0 || ny>w || ny<=0 ) continue; //出去了的舍弃;
//只有碰到了格挡物,才进行记录;
memcpy(map[rear],map[front],sizeof(map[front]));
map[rear][nz]=0;
nx=nx-dx[i];ny=ny-dy[i];nz=nx*w+ny;
q[rear]=nz; //printf("%d %d\n",nx,ny);for(int j=1;j<=h;j++){for(int k=1;k<=w;k++) {int p=j*w+k;printf("%d ",map[rear][p]);}printf("\n");}
dis[rear]=dis[front]+1;
rear++;
}
front++;
}
return -1; //未找到,输出-1;
}
int main()
{
int z;
while(scanf("%d%d",&w,&h)==2&&w!=0)
{
memset(map,0,sizeof(map));
for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++){
z=i*w+j; //用一维坐标记录;
scanf("%d",&map[0][z]);
if(map[0][z]==2)
z1=z;
}
printf("%d\n",B_search());
}
return 0;
}
/*
总结:
①做题之前看清题目意思,按题目要求做!
②BFS易出现runtime error错误,不知道为什么;
③要把所有情况都考虑到,特别是一些特殊元素;
*/