http://ac.jobdu.com/problem.php?id=1335
sun所在学校每年都要举行电脑节,今年电脑节有一个新的趣味比赛项目叫做闯迷宫。
sun的室友在帮电脑节设计迷宫,所以室友就请sun帮忙计算下走出迷宫的最少步数。
知道了最少步数就可以辅助控制比赛难度以及去掉一些没有路径到达终点的map。
比赛规则是:从原点(0,0)开始走到终点(n-1,n-1),只能上下左右4个方向走,只能在给定的矩阵里走。
输入有多组数据。
每组数据输入n(0<n<=100),然后输入n*n的01矩阵,0代表该格子没有障碍,为1表示有障碍物。
注意:如果输入中的原点和终点为1则这个迷宫是不可达的。
对每组输入输出该迷宫的最短步数,若不能到达则输出-1。
2 0 1 0 0 5 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0
2 8
#include <iostream>
#include <iomanip>
#include <cmath>
//#include <map>
#include <assert.h>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using
namespace
std;
const
int
MAXDIST = 10000;
int
map[105][105];
int
dist[105][105];
void
InitDist(
int
n)
{
for
(
int
i=0; i<=n; i++)
//多取一位
for
(
int
j=0; j<=n; j++)
dist[i][j]=MAXDIST;
}
int
computePath(
int
n)
{
if
(map[0][0]==1 || map[n-1][n-1]==1)
return
-1;
InitDist(n);
dist[0][0]=0;
for
(
int
i=1; i<n; i++)
if
(0 == map[0][i])
dist[0][i]=dist[0][i-1]+1;
for
(
int
i=1; i<n; i++)
if
(0==map[i][0])
dist[i][0]=dist[i-1][0]+1;
for
(
int
i=1;
i<n; i++)
for
(
int
j=1;
j<n; j++)
//红色部分为问题所在,后面类似
{
if
(0 == map[i][j])
{
int
temp1 = dist[i-1][j]+1;
int
temp2 = dist[i][j-1]+1;
int
temp = temp1<temp2 ? temp1:temp2;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
}
for
(
int
i=1; i<n; i++)
for
(
int
j=n-1; j>0; j--)
if
(0 == map[i][j])
{
int
temp1 = dist[i-1][j]+1;
int
temp2 = dist[i][j+1]+1;
int
temp = temp1<temp2 ? temp1:temp2;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=n-1; i>0; i--)
for
(
int
j=1; j<n; j++)
if
(0 == map[i][j])
{
int
temp1 = dist[i+1][j]+1;
int
temp2 = dist[i][j-1]+1;
int
temp = temp1<temp2 ? temp1:temp2;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=n-1; i>0; i--)
for
(
int
j=n-1; j>0; j--)
if
(0 == map[i][j])
{
int
temp1 = dist[i+1][j]+1;
int
temp2 = dist[i][j+1]+1;
int
temp = temp1<temp2 ? temp1:temp2;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=1; i<n; i++)
for
(
int
j=1; j<n; j++)
{
if
(0 == map[i][j])
{
int
temp1 = dist[i-1][j]+1;
int
temp2 = dist[i][j-1]+1;
int
temp = temp1<temp2 ? temp1:temp2;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
}
if
(dist[n-1][n-1]>=MAXDIST)
return
-1;
else
return
dist[n-1][n-1];
}
int
main()
{
//freopen("in.txt","r",stdin);
int
n;
while
(cin>>n)
{
for
(
int
i=0; i<n; i++)
for
(
int
j=0; j<n; j++)
cin>>map[i][j];
cout<<computePath(n)<<endl;
}
return
0;
}
纠正上面提到的问题果然AC了,
没有第五趟额外的扫描代码通过不了,所以暂时还不确定代码绝对正确,第五趟是否一定不会再有值更新并无把握,以后再仔细考虑吧,不过后面写的直到完全没值更新了才停止扫描(只朝一个方向扫描只为代码简洁,收敛速度会慢一些吧)160ms-》190ms
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <cmath>
//#include <map>
#include <assert.h>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using
namespace
std;
const
int
MAXDIST = 10000;
int
map[105][105];
int
dist[105][105];
void
InitDist(
int
n)
{
for
(
int
i=0; i<=n; i++)
//多取一位 从0取才有意义
for
(
int
j=0; j<=n; j++)
dist[i][j]=MAXDIST;
}
int
SourceForm(
int
x,
int
y,
int
n)
{
if
(x<0 || x>=n || y<0 || y>=n)
return
MAXDIST;
else
return
dist[x][y];
}
int
computePath(
int
n)
{
if
(map[0][0]==1 || map[n-1][n-1]==1)
return
-1;
InitDist(n);
dist[0][0]=0;
for
(
int
i=0; i<n; i++)
for
(
int
j=0; j<n; j++)
if
(0 == map[i][j])
{
int
temp = SourceForm(i-1,j,n)+1;
if
(SourceForm(i,j-1,n)+1<temp)
temp = SourceForm(i,j-1,n)+1;
if
(SourceForm(i+1,j,n)+1<temp)
temp = SourceForm(i+1,j,n)+1;
if
(SourceForm(i,j+1,n)+1<temp)
temp = SourceForm(i,j+1,n)+1;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=0; i<n; i++)
for
(
int
j=n-1; j>=0; j--)
if
(0 == map[i][j])
{
int
temp = SourceForm(i-1,j,n)+1;
if
(SourceForm(i,j-1,n)+1<temp)
temp = SourceForm(i,j-1,n)+1;
if
(SourceForm(i+1,j,n)+1<temp)
temp = SourceForm(i+1,j,n)+1;
if
(SourceForm(i,j+1,n)+1<temp)
temp = SourceForm(i,j+1,n)+1;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=n-1; i>=0; i--)
for
(
int
j=0; j<n; j++)
if
(0 == map[i][j])
{
int
temp = SourceForm(i-1,j,n)+1;
if
(SourceForm(i,j-1,n)+1<temp)
temp = SourceForm(i,j-1,n)+1;
if
(SourceForm(i+1,j,n)+1<temp)
temp = SourceForm(i+1,j,n)+1;
if
(SourceForm(i,j+1,n)+1<temp)
temp = SourceForm(i,j+1,n)+1;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=n-1; i>=0; i--)
for
(
int
j=n-1; j>=0; j--)
if
(0 == map[i][j])
{
int
temp = SourceForm(i-1,j,n)+1;
if
(SourceForm(i,j-1,n)+1<temp)
temp = SourceForm(i,j-1,n)+1;
if
(SourceForm(i+1,j,n)+1<temp)
temp = SourceForm(i+1,j,n)+1;
if
(SourceForm(i,j+1,n)+1<temp)
temp = SourceForm(i,j+1,n)+1;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
for
(
int
i=0; i<n; i++)
for
(
int
j=0; j<n; j++)
if
(0 == map[i][j])
{
int
temp = SourceForm(i-1,j,n)+1;
if
(SourceForm(i,j-1,n)+1<temp)
temp = SourceForm(i,j-1,n)+1;
if
(SourceForm(i+1,j,n)+1<temp)
temp = SourceForm(i+1,j,n)+1;
if
(SourceForm(i,j+1,n)+1<temp)
temp = SourceForm(i,j+1,n)+1;
if
(temp<dist[i][j])
dist[i][j]=temp;
}
if
(dist[n-1][n-1]>=MAXDIST)
return
-1;
else
return
dist[n-1][n-1];
}
int
main()
{
//freopen("in.txt","r",stdin);
int
n;
while
(cin>>n)
{
for
(
int
i=0; i<n; i++)
for
(
int
j=0; j<n; j++)
scanf
(
"%d"
,&map[i][j]);
//cin>>map[i][j];
cout<<computePath(n)<<endl;
}
return
0;
}
/**************************************************************
Problem: 1335
User: xjbscut
Language: C++
Result: Accepted
Time:160 ms
Memory:1600 kb
****************************************************************/
觉得传递思想绝对是OK的,使用了一种觉得严谨且暴力保证收敛的手段(每次都考虑四个紧邻,把相邻元素是否越界
封装在SourceForm(
int
x,
int
y,
int
n)中很优雅
)
#include <iostream>
#include <iomanip>
#include <cmath>
//#include <map>
#include <assert.h>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using
namespace
std;
const
int
MAXDIST = 10000;
int
map[105][105];
int
dist[105][105];
void
InitDist(
int
n)
{
for
(
int
i=0; i<=n; i++)
//多取一位 从0取才有意义
for
(
int
j=0; j<=n; j++)
dist[i][j]=MAXDIST;
}
int
SourceForm(
int
x,
int
y,
int
n)
{
if
(x<0 || x>=n || y<0 || y>=n)
return
MAXDIST;
else
return
dist[x][y];
}
int
computePath(
int
n)
{
if
(map[0][0]==1 || map[n-1][n-1]==1)
return
-1;
InitDist(n);
dist[0][0]=0;
bool
hasUpadated;
do
{
hasUpadated =
false
;
for
(
int
i=0; i<n; i++)
for
(
int
j=0; j<n; j++)
if
(0 == map[i][j])
{
//考虑四个相邻元素
int
temp = SourceForm(i-1,j,n)+1;
if
(SourceForm(i,j-1,n)+1<temp)
temp = SourceForm(i,j-1,n)+1;
if
(SourceForm(i+1,j,n)+1<temp)
temp = SourceForm(i+1,j,n)+1;
if
(SourceForm(i,j+1,n)+1<temp)
temp = SourceForm(i,j+1,n)+1;
if
(temp<dist[i][j])
{
dist[i][j]=temp;
hasUpadated =
true
;
}
}
}
while
(hasUpadated);
if
(dist[n-1][n-1]>=MAXDIST)
return
-1;
else
return
dist[n-1][n-1];
}
int
main()
{
//freopen("in.txt","r",stdin);
int
n;
while
(cin>>n)
{
for
(
int
i=0; i<n; i++)
for
(
int
j=0; j<n; j++)
scanf
(
"%d"
,&map[i][j]);
//cin>>map[i][j];
cout<<computePath(n)<<endl;