题目链接:点击打开链接
题目:
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 8639 | Accepted: 2895 |
Description
Input
Output
Sample Input
3 4 YBEB EERE SSTE 0 0
Sample Output
8
题意:
从Y到T,问最少步数。其中S和R不可走,B要花费两步。
思路:
这里有一个陷阱是,从一个非B的点走到紧邻它的B点花费2步。回到最朴素的bfs实现的思想上,bfs是逐层向下迭代的,所以保证第一次走到终点时的步数是最小的。其中最关键的一点是,从上一层到下一层的路径长度一定是全部相同的。在这题中,从某个点走到下个为B的点花费了两步,这和初始的定义相悖,这将导致走到终点的路径不是最小。很容易举出一个例子来证明这一点。
写法1:
这里我们可以用记忆化搜索,一个vis[i][j]数组表示走到(i,j)这个点时,花费的步数cnt,如果存在某一次到达这个点花费的步数更少我们就把vis[i][j]更新,否则就不这样走。
这样写,必须把所有的可行路径的搜索一遍,效率比较低。
PS:使用这种写法时,在剪枝那一步我写tc>vis[tx][ty]超时了,改成tc>=vis[tx][ty]就AC了,而且还是180ms左右。剪枝还是要能剪就剪!
写法2:
使用优先队列。这道题已经可以看成是求单源最短路了,优先队列可以保证像bfs一样逐层迭代,第一次到达终点时即答案。
写法一:
#include
#include
#include
#include
using namespace std;
const int MAXN = 305;
const int INF = 0x3f3f3f3f;
const int dx[4] = {0, 0, -1, 1};
const int dy[4] = {1, -1, 0, 0};
int m, n;
int vis[MAXN][MAXN];
char tu[MAXN][MAXN];
struct Node
{
int x, y, cnt;
Node(int x, int y, int cnt):x(x), y(y), cnt(cnt){}
};
Node st(0, 0, 0), ed(0, 0, 0);
void bfs(){
int ans = INF;
memset(vis, 0x3f, sizeof(vis));
queue q;
q.push(st);
vis[st.x][st.y] = 0;
while(!q.empty()){
Node tmp = q.front(); q.pop();
if(tmp.x==ed.x && tmp.y==ed.y && ans>tmp.cnt){
ans = tmp.cnt;
continue;
}
for(int i=0; i<4; ++i){
int tx = tmp.x + dx[i];
int ty = tmp.y + dy[i];
int tc = tmp.cnt + 1;
if(tx<0||ty<0||tx>=m||ty>=n) continue;
if(tu[tx][ty]=='S' || tu[tx][ty]=='R') continue;
if(tu[tx][ty]=='B') ++tc;
if(tc>=vis[tx][ty]) continue;
vis[tx][ty] = tc;
q.push(Node(tx, ty, tc));
}
}
if(INF==ans)
printf("%d\n", -1);
else
printf("%d\n", ans);
}
int main(){
while(scanf("%d%d", &m, &n)!=EOF){
if(m==0&&n==0) break;
for(int i=0; i
#include
#include
#include
#include
using namespace std;
const int MAXN = 305;
const int dx[4] = {0, 0, -1, 1};
const int dy[4] = {1, -1, 0, 0};
int m, n;
bool vis[MAXN][MAXN];
char tu[MAXN][MAXN];
struct Node
{
int x, y, cnt;
bool operator<(const Node &t)const{
return cnt>t.cnt;
}
Node(int x, int y, int cnt):x(x), y(y), cnt(cnt){}
};
Node st(0, 0, 0), ed(0, 0, 0);
int bfs(){
memset(vis, 0, sizeof(vis));
priority_queue q;
q.push(st);
vis[st.x][st.y] = true;
while(!q.empty()){
Node tmp = q.top(); q.pop();
if(tmp.x==ed.x && tmp.y==ed.y){
return tmp.cnt;
}
for(int i=0; i<4; ++i){
int tx = tmp.x + dx[i];
int ty = tmp.y + dy[i];
int tc = tmp.cnt + 1;
if(tx<0||ty<0||tx>=m||ty>=n || vis[tx][ty]) continue;
if(tu[tx][ty]=='S' || tu[tx][ty]=='R') continue;
if(tu[tx][ty]=='B') ++tc;
q.push(Node(tx, ty, tc));
vis[tx][ty] = true;
}
}
return -1;
}
int main(){
while(scanf("%d%d", &m, &n)!=EOF){
if(m==0&&n==0) break;
for(int i=0; i