1. 程式人生 > >1005: Biggest Number解題報告---DFS & BFS & 強剪枝

1005: Biggest Number解題報告---DFS & BFS & 強剪枝

                                     1005: Biggest Number

時間限制: 1  記憶體限制: 128 MB

題目描述

You have a maze with obstacles and non-zero digits in it:

You can start from any square, walk in the maze, and finally stop at some square. Each step, you may only walk into one of the four neighbouring squares (up, down, left, right) 

and you cannot walk into obstacles or walk into a square more than once. When you finish, you can get a number by writing down the digits you encounter in the same order as you meet them. For example, you can get numbers 9784, 4832145 etc. The biggest number you can get is 791452384, shown in the picture above.

Your task is to find the biggest number you can get.

輸入

There will be at most 25 test cases. Each test begins with two integers R and C (2<=R,C<=15, R*C<=30), the number of rows and columns of the maze. The next R rows represent the maze. Each line contains exactly C

 characters (without leading or trailing spaces), each of them will be either '#' or one of the nine non-zero digits. There will be at least one non-obstacle squares (i.e. squares with a non-zero digit in it) in the maze. The input is terminated by a test case with R=C=0, you should not process it.

輸出

For each test case, print the biggest number you can find, on a single line.

樣例輸入

3 7
##9784#
##123##
##45###
0 0

樣例輸出

791452384

參考了CSDN大佬的強剪枝(膜拜.jpg) 

BFS來獲取任意點的可達最長路徑,用於剪枝,DFS實現最大值的獲取與更新,本題用string實現字串拼接與大小比較,當然也可用strcmp與strcat函式實現,較麻煩一點。

AC Code: 

#include <iostream>
#include<cstdint>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<climits>
#include<map>
#include<queue>
using namespace std;
static const int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}};
bool vis[20][20], used[20][20];
int n, m;
char maps[20][20], str[35];
string res, s1, s2;
struct Point{   
    int x, y;
};
 
bool is_bound(int x, int y){
    return (x >= 0 && x < n && y >= 0 && y < m && maps[x][y] != '#');
}
int path(int x, int y){     //獲取x,y點可達最長路徑
    Point p1, p2;
    int tail = 0;
    p1.x = x, p1.y = y;
    for(int i = 0; i < n; i++){
        for(int j = 0; j < m; j++){
            used[i][j] = vis[i][j];
        }
    }
    queue<Point>q;
    q.push(p1);
    while(!q.empty()){
        p1 = q.front();
        q.pop();
        for(int i = 0; i < 4; i++){
            p2.x = p1.x + dir[i][0];
            p2.y = p1.y + dir[i][1];
            if(is_bound(p2.x, p2.y) && !used[p2.x][p2.y]){
                used[p2.x][p2.y] = true;
                str[tail++] = maps[p2.x][p2.y];
                q.push(p2);
            }
        }
    }
    str[tail] = '\0';
    return tail;
}
void dfs(int x, int y, string s){
    int len = path(x, y);
    if(s.length() > res.length() || (s.length() == res.length() && s > res)){
        res = s;    //最大值更新
    }
    if(len + s.length() < res.length()) return; //長度比res小的剪枝
    if(len + s.length() == res.length()){   //長度相等,大小可能超過res
        sort(str, str + len);   //獲取路徑最大值用於剪枝
        s2 = s;
        for(int i = len - 1; i >= 0; i--){  //s2最大值
            s2 += str[i];
        }
        if(s2 < res) return;    //長度相等,字串小的剪枝
    }
    for(int i = 0; i < 4; i++){
        int fx = x + dir[i][0];
        int fy = y + dir[i][1];
        if(is_bound(fx, fy) && !vis[fx][fy]){
            vis[fx][fy] = true;
            dfs(fx, fy, s + maps[fx][fy]);
            vis[fx][fy] = false;    //回溯
        }
    }
}
int main(){
    while(scanf("%d%d", &n, &m) != EOF){
        if(n == 0 && m == 0) break;
        memset(vis, false, sizeof(vis));
        res = "";
        for(int i = 0; i < n; i++){
            scanf("%s", maps[i]);
        }
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                if(maps[i][j] != '#'){
                    vis[i][j] = true;
                    s1 = "";
                    dfs(i, j, s1 + maps[i][j]);
                    vis[i][j] = false;
                }
            }
        }
//        cout<<res<<endl;
        printf("%s\n", res.c_str());
    }
    return 0;
}