[USACO11OPEN]Corn Maze S

Posted zhyyyyy115

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[USACO11OPEN]Corn Maze S相关的知识,希望对你有一定的参考价值。

[USACO11OPEN]Corn Maze S

题面翻译

奶牛们去一个 \\(N\\times M\\) 玉米迷宫,\\(2 \\leq N \\leq 300,2 \\leq M \\leq300\\)

迷宫里有一些传送装置,可以将奶牛从一点到另一点进行瞬间转移。这些装置可以双向使用。

如果一头奶牛处在这个装置的起点或者终点,这头奶牛就必须使用这个装置。

玉米迷宫除了唯一的一个出口都被玉米包围。

迷宫中的每个元素都由以下项目中的一项组成:

  1. 玉米,# 表示,这些格子是不可以通过的。
  2. 草地,. 表示,可以简单的通过。
  3. 传送装置,每一对大写字母 \\(\\ttA\\)\\(\\ttZ\\) 表示。
  4. 出口,= 表示。
  5. 起点, @ 表示

奶牛能在一格草地上可能存在的四个相邻的格子移动,花费 \\(1\\) 个单位时间。从装置的一个结点到另一个结点不花时间。

输入格式

第一行:两个用空格隔开的整数 \\(N\\)\\(M\\)

\\(2\\sim N+1\\) 行:第 \\(i+1\\) 行描述了迷宫中的第 \\(i\\) 行的情况(共有\\(M\\)个字符,每个字符中间没有空格)。

输出格式

一个整数,表示起点到出口所需的最短时间。

样例 #1

样例输入 #1

5 6
###=##
#.W.##
#.####
#.@W##
######

样例输出 #1

3

提示

例如以下矩阵,\\(N=5,M=6\\)

###=##
#.W.##
#.####
#.@W##
######

唯一的一个装置的结点用大写字母 \\(\\ttW\\) 表示。

最优方案为:先向右走到装置的结点,花费一个单位时间,再到装置的另一个结点上,花费 \\(0\\) 个单位时间,然后再向右走一个,再向上走一个,到达出口处,总共花费了 \\(3\\) 个单位时间。

题解(bfs)

这一题其实就是一个广度优先遍历,但是这一题的坑点在于,他有一个传送门,我们要注意,传送门不需要记录通过多少次,我们只需要限制每个草地和起点经过一次就可以了,以防止死循环。
因为传送门有两个方向的请况,所以我们不能限制经过传送门的次数,但是这样并不会进入死循环,因为你走到这个传送门后,你之前走的草地都不能走了,所以并不会造成死循环。

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define ppb pop_back
#define SZ(v) ((int)v.size())
#define pii pair<int, int>
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef double db;
using namespace std;
const int N = 1e4+10;
int _;
int n, m;
char mp[N][N], vis[N][N];
int xx1, yy1;
int ans = INT_MAX;
int dx[] = 0, 1, 0, -1;
int dy[] = -1, 0, 1, 0;
bool check(int x, int y) 
    if(x < 1 || y < 1 || x > n || y > m) return false;
    return true;

struct node 
    int x, y, step;
;
pii f(int x, int y)                        // 找到对应位置的传送门
    for(int i = 1; i <= n; i++) 
        for(int j = 1; j <= m; j++) 
            if(i == x && j == y) continue;
            if(mp[i][j] == mp[x][y]) return make_pair(i, j);
        
    
    return 0, 0;

void bfs() 
    queue<node> q;
    q.push(xx1, yy1, 0);
    vis[xx1][yy1] = 1;
    while(!q.empty()) 
        node tmp = q.front();
        q.pop();
        // cout << tmp.x << " " << tmp.y << " " << tmp.step << "\\n";
        if(mp[tmp.x][tmp.y] == \'=\') 
            cout << tmp.step << "\\n";
            return;
        
        for(int i = 0; i < 4; i++) 
            int xx = tmp.x + dx[i];
            int yy = tmp.y + dy[i];
            if(check(xx, yy)) 
                if(mp[xx][yy] == \'.\' && vis[xx][yy] == 0) 
                    vis[xx][yy] = 1;
                    q.push(xx, yy, tmp.step+1);
                 else if(mp[xx][yy] >= \'A\' && mp[xx][yy] <= \'Z\') 
                    pii t = f(xx, yy);
                    q.push(t.fi, t.se, tmp.step+1);
                 else if(mp[xx][yy] == \'=\') 
                    vis[xx][yy] = 1;
                    q.push(xx, yy, tmp.step+1);
                
            
        
    

void solve() 
   cin >> n >> m;
   for(int i = 1; i <= n; i++) 
        for(int j = 1; j <= m; j++) 
            cin >> mp[i][j];
            if(mp[i][j] == \'@\') 
                xx1 = i, yy1 = j;
            
        
    
    bfs();
   

int main() 
    ios::sync_with_stdio(false);
    cin.tie(nullptr); 
    _ = 1;
    // cin >> _;
    while(_--) 
        solve();
    
    return 0;

bzoj 3299 [USACO2011 Open]Corn Maze玉米迷宫(最短路)

 

就一个最短路,并且边长都是1,所以每个点只搜一次。

 

 1 /**************************************************************
 2     Problem: 3299
 3     User: MT_Chan
 4     Language: C++
 5     Result: Accepted
 6     Time:72 ms
 7     Memory:2420 kb
 8 ****************************************************************/
 9  
10 #include<cstdio>
11 #include<cstdlib>
12 #include<cstring>
13 #include<iostream>
14 #include<algorithm>
15 #include<queue>
16 using namespace std;
17 #define Maxn 310
18 #define INF 0xfffffff
19  
20 int kx[30];
21 int a[Maxn][Maxn],tr[Maxn*Maxn];
22 char s[Maxn];
23  
24 int dis[Maxn*Maxn],st,ed;
25 int n,m;
26  
27 queue<int > q;
28 void spfa()
29 {
30     while(!q.empty()) q.pop();
31     memset(dis,-1,sizeof(dis));
32     q.push(st);dis[st]=0;
33     while(!q.empty())
34     {
35         int x=q.front();
36         int nx=(x-1)/m+1,ny=x-(nx-1)*m;
37         if(ny>1&&tr[x-1]!=-1&&dis[tr[x-1]]==-1)
38         {
39             dis[tr[x-1]]=dis[x]+1;
40             if(tr[x-1]==ed) break;
41             q.push(tr[x-1]);
42         }
43         if(ny<m&&tr[x+1]!=-1&&dis[tr[x+1]]==-1)
44         {
45             dis[tr[x+1]]=dis[x]+1;
46             if(tr[x+1]==ed) break;
47             q.push(tr[x+1]);
48         }
49         if(nx>1&&tr[x-m]!=-1&&dis[tr[x-m]]==-1)
50         {
51             dis[tr[x-m]]=dis[x]+1;
52             if(tr[x-m]==ed) break;
53             q.push(tr[x-m]);
54         }
55         if(nx<n&&tr[x+m]!=-1&&dis[tr[x+m]]==-1)
56         {
57             dis[tr[x+m]]=dis[x]+1;
58             if(tr[x+m]==ed) break;
59             q.push(tr[x+m]);
60         }
61         q.pop();
62     }
63     printf("%d\\n",dis[ed]);
64 }
65  
66 int main()
67 {
68     scanf("%d%d",&n,&m);
69     memset(kx,-1,sizeof(kx));
70     memset(tr,0,sizeof(tr));
71     for(int i=1;i<=n;i++)
72     {
73         scanf("%s",s);
74         for(int j=0;j<m;j++)
75         {
76             int now=(i-1)*m+j+1;
77             if(s[j]==\'@\') st=now;
78             else if(s[j]==\'=\') ed=now;
79             else if(s[j]==\'#\') tr[now]=-1;
80             else if(s[j]>=\'A\'&&s[j]<=\'Z\')
81             {
82                 int kk=s[j]-\'A\'+1;
83                 if(kx[kk]==-1) kx[kk]=now;
84                 else tr[now]=kx[kk],tr[kx[kk]]=now;
85             }
86         }
87     }
88     for(int i=1;i<=n*m;i++) if(tr[i]==0) tr[i]=i;
89     spfa();
90     return 0; 
91 }
View Code

 

以上是关于[USACO11OPEN]Corn Maze S的主要内容,如果未能解决你的问题,请参考以下文章

[USACO11OPEN]玉米田迷宫Corn Maze

洛谷 P1825 [USACO11OPEN]玉米田迷宫Corn Maze

luogu P1825 [USACO11OPEN]玉米田迷宫Corn Maze 题解

bzoj 3299 [USACO2011 Open]Corn Maze玉米迷宫(最短路)

[USACO2011 Open]Corn Maze玉米迷宫

[uva11OPEN]玉米田迷宫Corn Maze(广搜bfs)