带限制条件的广搜

最近吃鸡游戏非常火,你们wyh学长也在玩这款游戏,这款游戏有一个非常重要的过程,就是要跑到安全区内,否则就会中毒持续消耗血量,我们这个问题简化如下

假设地图为n*n的一个图,图中有且仅有一块X的联通快代表安全区域,有一个起点S代表缩圈的时候的起点,图中C代表的是车(保证车的数量小于等于100),标记为.的代表空地,可以任意通过,O代表障碍物不能通过。每次没有车的时候2s可以走一个格(只能走自己的上下左右4个方向),有车的话时间为1s走一个格

现在告诉你最多能坚持的时间为t秒,问你在t秒内(含t秒)能否从s点到达安全区域,能的话输出YES,并且输出最短时间,不能的话输出NO

输入描述:

输入第一行一个整数T(1<=T<=10)
接下来有T组测试数据,每组测试数据输入2个数n和k(1<=n<=100,1<=k<=10^9)
接下来n行,每行n个字符,代表对应的n*n的地图,每个字符都是上面的一种,并且保证只有一个起点,只有一块安全区域。

输出描述:

对于每组测试数据,先输出能否到达,能的话输出YES,然后换行输出最短时间,如果不能的话直接输出NO
示例1

输入

3
2 3
.X
S.
2 3
.X
SC
2 4
.X
S.

输出

NO
YES
3
YES
4

题意 : 给你一个图,问能否在最短的时间内到达终点,途中有车可以骑,会使前进速度加快。
思路分析:正常的广搜,不过加多了个限制条件,就是你先到达的点不一定就是最优的,因为有车子的存在,所有,记录步数的数组多开一个维度就可以了,这样就不会失去最优解,类似的你可以多开2维或3维去解决问题。
代码示例 :
#define ll long long
const int maxn = 1e6+5;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
 
int n, k;
int sx, sy;
struct node
{
    int x, y;
    int pt; // 0 表示没车 1 表示有车
    node(int _x, int _y, int _pt):x(_x), y(_y), pt(_pt){}
};
queue<node>que;
int bu[105][105][2];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
char mp[105][105];
 
bool check(int x, int y){
    if (x >= 1 && x <= n && y >= 1 && y <= n && mp[x][y] != 'O') return true;
    return false;
}
int ans = inf;

void bfs(int x, int y){
    while(!que.empty()) que.pop();
    que.push(node(x, y, 0));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            for(int k = 0; k <= 1; k++) bu[i][j][k] = inf;
        }
    }
    bu[x][y][0] = 0;
    
    while(!que.empty()){
        node v = que.front();
        que.pop();
        
        if (mp[v.x][v.y] == 'X') {
            ans = min(bu[v.x][v.y][v.pt], ans);
            continue;
        }
        for(int i = 0; i < 4; i++){
            int fx = v.x+dir[i][0];
            int fy = v.y+dir[i][1];
            
            if (check(fx, fy)){
                if (v.pt == 1){
                    if (bu[v.x][v.y][1]+1 < bu[fx][fy][1]) {
                        bu[fx][fy][1] = bu[v.x][v.y][1]+1;
                        que.push(node(fx, fy, 1));
                    }
                }
                else {
                    if (mp[fx][fy] == 'C'){
                        if (bu[v.x][v.y][0]+2 < bu[fx][fy][1]) {
                            bu[fx][fy][1] = bu[v.x][v.y][0]+2;
                            que.push(node(fx, fy, 1));
                        }
                    }
                    else {
                        if (bu[v.x][v.y][0]+2 < bu[fx][fy][0]) {
                            bu[fx][fy][0] = bu[v.x][v.y][0]+2;
                            que.push(node(fx, fy, 0));
                        }
                    }
                }
            }
        }
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int t;
     
    cin >> t;
    while(t--){
        scanf("%d%d", &n, &k);
        int sign = 0;
        for(int i = 1; i <= n; i++){
            scanf("%s", mp[i]+1);
            for(int j = 1; j <= n; j++){
                if (mp[i][j] == 'S') {
                    sx = i, sy = j;
                }
            }
        }
        ans = inf;
        bfs(sx, sy);
        if (ans > k) printf("NO
");
        else printf("YES
%d
", ans);
       //printf("%d
", ans); 
    }
    return 0;
}

 其实这题最开始写的时候是按照spfa的思想去写的,但是错在了50%,还没找到原因,待更新,先贴个代码。

#define ll long long
const int maxn = 1e6+5;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
 
int n, k;
int sx, sy;
struct node
{
    int x, y;
    int pt; // 0 表示没车 1 表示有车
    node(int _x, int _y, int _pt):x(_x), y(_y), pt(_pt){}
};
queue<node>que;
bool vis[105][105];
int bu[105][105];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
char mp[105][105];
 
bool check(int x, int y){
    if (x >= 1 && x <= n && y >= 1 && y <= n && mp[x][y] != 'O') return true;
    return false;
}
int ans = inf;
void bfs(int x, int y){
    while(!que.empty()) que.pop();
    que.push(node(x, y, 0));
    memset(vis, false, sizeof(vis));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++) bu[i][j] = inf;
    }
    int c = 1;
    bu[x][y] = 0;
    while(!que.empty()){
        node v = que.front();
        que.pop();
        
        vis[v.x][v.y] = false;
        if (mp[v.x][v.y] == 'X') {
            ans = min(ans, bu[v.x][v.y]);
        }
        for(int i = 0; i < 4; i++){
            int fx = v.x+dir[i][0];
            int fy = v.y+dir[i][1];
               
            if (v.pt == 1) c = 1;
            else c = 2; 
            if (check(fx, fy) && bu[v.x][v.y]+c <= bu[fx][fy]){
                bu[fx][fy] = bu[v.x][v.y]+c;
                if (!vis[fx][fy]){
                    if (mp[fx][fy] == 'C' || v.pt == 1) que.push(node(fx, fy, 1));
                    else que.push(node(fx, fy, 0));
                    vis[fx][fy] = true;
                }
            }
        }    
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int t; 
    cin >> t;
    while(t--){
        scanf("%d%d", &n, &k);
        int sign = 0;
        for(int i = 1; i <= n; i++){
            scanf("%s", mp[i]+1);
            for(int j = 1; j <= n; j++){
                if (mp[i][j] == 'S') {
                    sx = i, sy = j;
                }
            }
        }
        ans = inf;
        bfs(sx, sy);
        if (ans > k) printf("NO
");
        else printf("YES
%d
", ans);
       //printf("%d
", ans); 
    }
    return 0;
}

2 .

Woken up by the alarm clock Igor the financial analyst hurried up to the work. He ate his breakfast and sat in his car. Sadly, when he opened his GPS navigator, he found that some of the roads in Bankopolis, the city where he lives, are closed due to road works. Moreover, Igor has some problems with the steering wheel, so he can make no more than two turns on his way to his office in bank.

Bankopolis looks like a grid of n rows and m columns. Igor should find a way from his home to the bank that has no more than two turns and doesn't contain cells with road works, or determine that it is impossible and he should work from home. A turn is a change in movement direction. Igor's car can only move to the left, to the right, upwards and downwards. Initially Igor can choose any direction. Igor is still sleepy, so you should help him.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 1000) — the number of rows and the number of columns in the grid.

Each of the next n lines contains m characters denoting the corresponding row of the grid. The following characters can occur:

  • "." — an empty cell;
  • "*" — a cell with road works;
  • "S" — the cell where Igor's home is located;
  • "T" — the cell where Igor's office is located.

It is guaranteed that "S" and "T" appear exactly once each.

Output

In the only line print "YES" if there is a path between Igor's home and Igor's office with no more than two turns, and "NO" otherwise.

Examples
Input
Copy
5 5
..S..
****.
T....
****.
.....
Output
YES
Input
Copy
5 5
S....
****.
.....
.****
..T..
Output
NO
Note

The first sample is shown on the following picture:

In the second sample it is impossible to reach Igor's office using less that 4 turns, thus there exists no path using no more than 2 turns. The path using exactly 4 turns is shown on this picture:

题意 : 问在拐弯次数不超过2次的前提下能否到达终点

思路分析 : 普通的广搜,多了一个转弯次数的限制,思路同上,有两种不同的写法

#define ll long long
const int maxn = 1e6+5;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;

int n, m;
char mp[1005][1005];
int sx, sy;
struct node
{
    int x, y;
    int f;
    node(int _x, int _y, int _f):x(_x), y(_y), f(_f){}
};
queue<node>que;
int bu[1005][1005][4];
int dir[4][2] = {0, 1, -1, 0, 1, 0, 0, -1};
bool check(int x, int y){
    if (x >= 1 && x <= n && y >= 1 && y <= m && mp[x][y] != '*') return true;
    return false;
}
int sign = 0;
void bfs(int x, int y, int f){
    while(!que.empty()) que.pop();
    que.push(node(x, y, f));
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            for(int k = 0; k < 4; k++){
                bu[i][j][k] = inf;
            }
        }
    }
    bu[x][y][f] = 0;
    
    while(!que.empty()){
        node v = que.front();
        que.pop();
        
        if (bu[v.x][v.y][v.f] > 2) continue;
        if(mp[v.x][v.y] == 'T'){
            sign = 1;
            return;
        }
        for(int i = 0; i < 4; i++){
            int fx = dir[i][0]+v.x;
            int fy = dir[i][1]+v.y;
            
            if (check(fx, fy)){
                if (i == v.f) {
                    if (bu[v.x][v.y][v.f] < bu[fx][fy][i]){
                        bu[fx][fy][i] = bu[v.x][v.y][v.f];
                        que.push(node(fx, fy, i));
                    }
                }
                else {
                    if (bu[v.x][v.y][v.f]+1 < bu[fx][fy][i]){
                        bu[fx][fy][i] = bu[v.x][v.y][v.f]+1;
                        que.push(node(fx, fy, i));
                    }
                }
            }
        }
    }
}

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    cin >>n >> m;
    for(int i = 1; i<= n; i++){
        scanf("%s", mp[i]+1);
        for(int j = 1; j <= m; j++){
            if (mp[i][j] == 'S') {sx = i; sy = j;}
        }
    }
    for(int i = 0; i < 4; i++){
        bfs(sx, sy, i);
        if (sign) {
            printf("YES
");
            return 0;
        }
        //printf("____________
");
    }
    printf("NO
");
    return 0;
}
#define ll long long
int n, m;
char mp[1005][1005];
int sx, sy, gx, gy;
 
struct node
{
    int x, y;
    int f, c;
    node(int _x = 0, int _y = 0, int _f = 0, int _c = 0):x(_x), y(_y), f(_f), c(_c){}
    bool operator< (const node &v)const{
        return c > v.c;
    }
};
priority_queue<node>que;
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int sign = 0;
int yy[1005][1005];
 
void bfs(int x, int y, int pt){
    while(!que.empty()) que.pop();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            yy[i][j] = inf;
        }
    }
    yy[x][y] = 0;
    que.push(node(x, y, pt, 0));
     
    while(!que.empty()){
        node v = que.top();
        que.pop();
        if (v.c > 2 || sign) continue;
        if (v.x == gx && v.y == gy) {sign = 1; return;}
        for(int i = 0; i < 4; i++){
            int fx = dir[i][0] + v.x;
            int fy = dir[i][1] + v.y;
             
            if (fx >= 1 && fx <= n && fy >= 1 && fy <= m && mp[fx][fy] != '*'){
                 
                if (v.f == i && v.c < yy[fx][fy]) {
                    yy[fx][fy] = v.c;
                    que.push(node(fx, fy, i, v.c));
                }
                else {
                    if (v.c+1 < yy[fx][fy]){
                        yy[fx][fy] = v.c + 1;
                        que.push(node(fx, fy, i, v.c+1));
                    }
                } 
            }
        }   
    }
}
 
int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++){
        scanf("%s", mp[i]+1);
        for(int j = 1; j <= m; j++){
            if (mp[i][j] == 'S') {sx = i; sy = j; break;}
        }
        for(int j = 1; j <= m; j++){
            if (mp[i][j] == 'T') {gx = i; gy = j; break;}
        }   
    }
    //int i = 1;
    for(int i = 0; i < 4; i++){
        bfs(sx,sy,i);
        if (sign) break;
    }
     
    if (sign) printf("YES
");
    else printf("NO
");
    return 0;
}
东北日出西边雨 道是无情却有情
原文地址:https://www.cnblogs.com/ccut-ry/p/8746810.html