(深搜)UVA - 1600 Patrol Robot

原題鏈接:

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=825&page=show_problem&problem=4475


題意:

在m*n的地圖上,有障礙物(1)和空地(0),機器人要通過走上下左右四個方向從左上角(1,1)走到右下角(n,m),但不能連續超過k個障礙,要求最短步數。


感悟:

刷紫書遇到的一題,一開始還很輕視的寫了一個dfs,發現過不了樣例,之後才發現是連續空格,稍微改下,過了樣例就提交了,結果是TLE。評估下,要麼就是dfs中判斷的不夠嚴格,需要剪枝,要麼就是這題dfs必定超時,只能用bfs。先嚐試前一種,發現平從我定義的狀態中以我的水無法再優化剪枝,思考了一下bfs,感覺按照我dfs的思路,寫出來的bfs必定WA。最後查看了題解,發現dfs,bfs都有人寫,才知道自己在搜索上的造詣依然淺薄。


分析:

按照最基本的搜索題,我們都要定義一個vis二維數組,記錄該點是否走過,並通過它達到回溯的目的。
但在這題中,機器人走路會有更多的分支選擇,比如在走到同一點,有兩種同一步數的走法,但是到達這一點所破除的障礙數量卻不同,在這裏我們需要選擇障礙物更少的,因爲很有可能在以後破除障礙能更快到達終點。用一個vis[][][]三維數組就可以記錄這樣一種狀態,前兩維記錄座標,第三維記錄已經破除障礙物的數量,數組值表示走的步數,與上邊一樣的道理,到達相同點並且破除障礙物數量相同時,應該選擇步數最小的。


代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <cctype>
#include <list>

#define ll long long
#define ull unsigned long long
#define VNAME(name) (#name)
#define debug(a) cout<<VNAME(a)<<" = "<<(a)<<endl;

using namespace std;

const int maxn = 100010;
const int inf = 1 << 30;

int maps[21][21];
int vis[21][21][21];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int n,m,k;
int ans;

int dfs(int x,int y,int step,int pok){
    if(x==n&&y==m){
        return step;
    }
    int ans=inf;
    for(int i=0;i<4;i++){
        int tx=x+dx[i];
        int ty=y+dy[i];
        int tp=pok;
        if(maps[tx][ty]==1)tp++;
        else tp=0;
        if(tx>=1&&tx<=n&&ty>=1&&ty<=m){
            if((vis[tx][ty][tp]<0||vis[tx][ty][tp]>step+1)&&tp<=k){
                vis[tx][ty][tp]=step+1;
                ans=min(ans,dfs(tx,ty,step+1,tp));
            }
        }
    }
    return ans;
}

int main() {
    //iostream::sync_with_stdio(false);

#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
#endif
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                scanf("%d",&maps[i][j]);
            }
        }
        memset(vis,-1,sizeof(vis));
        int ans=dfs(1,1,0,0);
        if(ans==inf){
            puts("-1");
        }
        else{
            printf("%d\n",ans);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章