【描述】
最近,全国的遥控赛车好手们都会聚一堂,参加一年一度的CSOM遥控赛车大赛。CSOM遥控赛车大赛有着相当悠久的历史,虽然在每一年的比赛中,竞赛组委会都会根据实际的需要设立新的比赛规则,有些选手可能会难以适应,但也正是由于这种不断创新的精神,使得更多的人参与了进来,比赛也因此获得了空前的成功。前几年的CSOM竞赛,都是选用一块大小为N×M的场地作为赛场,要求选手的赛车在最短的时间内从起点移动到终点。虽然赛场的地形高低有少许的起伏,但并不存在无法到达的地点,因而在这种赛制下,只要选手赛车的马力足够大,就可以占据极大的优势。随着这几年的比赛的进行,赛车的性能虽然产生了很大的提高,但由于受到技术水平的限制,提高的幅度已日见缩小。为了使比赛的内容更加新颖,难度更具挑战性,CSOM竞赛组委会研究出了一种新的竞赛规则,其中最大的改变就是在赛场上增加了许多无法穿越的障碍物,若赛车在到达终点前撞上障碍物,就视为任务失败。在赛车的马力和灵活性等性能相差较小的情况下,要控制速度极快的赛车绕开障碍物移动到终点,最关键的是提高选手的反应灵敏度(即两次改变赛车运动方向所间隔的最短时间,也可称为选手的反应时间),使自己能够更快地控制赛车改变前进的方向。当然,由于选手反应灵敏度的不同,可选择的路径就会大不相同。如下图所示,对于同一个赛场,两位选手的反应时间分别为2秒和1秒,而其到达终点所需的时间分别为18秒和16秒(赛车每秒可沿当前方向移动一格,从起点出发时算改变一次方向)。
(图片就是样例输入)
由以上两图可知,赛车的最短路线长度是由选手的反应灵敏度所决定的,当选手的反应很慢时,可能就不会存在可行的路径。你的任务便是:在能够完成赛程(即存在从起点到终点的路径)的条件下,求出选手所有可能的反应时间,以及每个可能的反应时间所对应的最短路线的长度。
【输入格式】
输入文件的第一行包含两个整数N和M,表示赛场的长和宽。第二行有四个整数x1、y1、x2、y2,表示赛程的起点和终点的位置分别为(x1,y1)和(x2,y2)。接下来N行是一个N×M的01矩阵,矩阵中第i行第j列元素Aij=1表示赛场中位置(i,j)为赛道,Aij=0表示赛场中位置(i,j)有障碍物。
【输出格式】
输出文件可能有多行,其中每行输出一个可能的选手反应时间及该时间所对应的最短路线长度。输出文件中必须包含所有符合题目要求的选手反应时间。
【样例输入】
10 10
1 4 10 7
0 0 0 1 0 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0
0 0 0 1 0 1 0 0 0 0
1 1 1 1 0 1 1 1 1 0
1 0 0 0 0 0 0 0 1 0
1 0 1 1 1 0 1 1 1 0
1 1 1 0 1 1 1 0 1 0
0 0 1 0 0 0 0 0 1 0
0 0 1 1 1 1 1 1 1 0
0 0 0 0 0 0 1 0 0 0
【样例输出】
1 16
2 18
【分析】
显然的最短路。每个可以到的的地方就是一个点。注意边长的确定。我的构图方法是首先连出所有的边,然后在SPFA的过程中限制边的长度(>=t)。第一次写的时候,没枚举一次t构一次图,限制边长>t, 超时。一想一个点才最多4n条边,于是更改了构图的方法。还有一个点SPFA的队列开短了……于是又乘了一个maxn。恩,很不错的题目。
#include <stdio.h> #include <string.h> #define maxn 110 #define MAXINT 1000000000 bool _map[maxn][maxn]; struct ss { int xx,yy,di; } bl[maxn][maxn][5*maxn]; int num[maxn][maxn]; int dis[maxn][maxn]; bool v[maxn][maxn]; int l,r,t,n,m; int sx,sy,ex,ey,ans; int temp; struct sss { int x,y; } q[maxn*maxn*maxn]; bool inmap(int x,int y) { return ((x>0)&&(x<=n)&&(y>0)&&(y<=m)); } void findl(int x,int y) { if (!_map[x][y]) return; int tx,ty; tx=x-1; ty=y; while ((inmap(tx,ty))&&(_map[tx][ty])) { bl[x][y][++num[x][y]].xx=tx; bl[x][y][num[x][y]].yy=ty; bl[x][y][num[x][y]].di=x-tx; --tx; } tx=x; ty=y+1; while ((inmap(tx,ty))&&(_map[tx][ty])) { bl[x][y][++num[x][y]].xx=tx; bl[x][y][num[x][y]].yy=ty; bl[x][y][num[x][y]].di=ty-y; ++ty; } tx=x+1; ty=y; while ((inmap(tx,ty))&&(_map[tx][ty])) { bl[x][y][++num[x][y]].xx=tx; bl[x][y][num[x][y]].yy=ty; bl[x][y][num[x][y]].di=tx-x; ++tx; } tx=x; ty=y-1; while ((inmap(tx,ty))&&(_map[tx][ty])) { bl[x][y][++num[x][y]].xx=tx; bl[x][y][num[x][y]].yy=ty; bl[x][y][num[x][y]].di=y-ty; --ty; } } void solve() { memset(v,0,sizeof(v)); l=r=0; ans=0; for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) dis[i][j]=MAXINT; dis[sx][sy]=0; v[sx][sy]=1; q[0].x=sx; q[0].y=sy; while (l<=r) { int tx=q[l].x,ty=q[l].y; for (int i=1;i<=num[tx][ty];++i) { int nx=bl[tx][ty][i].xx,ny=bl[tx][ty][i].yy,nd=bl[tx][ty][i].di; if ((nd<t)&&(!((nx==ex)&&(ny==ey)))) continue; if (dis[tx][ty]+nd<dis[nx][ny]) { dis[nx][ny]=dis[tx][ty]+nd; if (!v[nx][ny]) { v[nx][ny]=1; q[++r].x=nx; q[r].y=ny; } } } v[tx][ty]=0; ++l; } ans=dis[ex][ey]; } int main() { freopen("racing.in","r",stdin); freopen("racing.out","w",stdout); scanf("%d%d",&n,&m); scanf("%d%d%d%d",&sx,&sy,&ex,&ey); for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) { scanf("%d",&temp); if (temp) _map[i][j]=1; } for (int i=1;i<=n;++i) for (int j=1;j<=m;++j) findl(i,j); for (t=1;t<=10;++t) { solve(); if (ans>=MAXINT) break; printf("%d %d\n",t,ans); } return 0; }