F - Honeycomb

题目链接
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题意:从起点‘S’到终点‘T’经过的最少方格数,如果不能到达‘T’就输出-1。

思路:从起点BFS一下,把每个六边形的中心看做一个点。蜜蜂可以向六个方向移动,分别判断一下能否到达另一个相邻的六边形并判断是否是终点。记录一下最短的路径。

再总结一下做这个题遇到的一些困难:
①在输入的时候花了很长时间,因为使用gets可能导致堆栈溢出覆盖之前输入的内容,这次就用了cin.getline()输入,可是之前使用的次数不多,没有深入了解过cin.getline(),使用的不是很熟练,输入的时候发现输入的图形不能输出,于是上网查资料,是因为输入一行字符串之后敲回车,产生的换行符仍然滞留在输入流里,接着cin.getline()把回车读入进去,解决的方法就是使用cin.ignore(),这个函数的作用与getchar()吃掉空格一样,可是原文章中写道cin.ignore()的效果与getchar()效果一样,但是我把他俩替换掉之后还是不能输出图形,我也不知道为什么。(参考文章:https://www.cnblogs.com/zz-1120-wtenlb/p/10567599.html)

②解决输入问题之后交了一发结果TLE,又优化了一点,就是把vis数组去掉,其中vis数组表示某个六边形是否进入队列,因为在每组输入的时候都要对vis进行初始化,可能这会让费时间,那么直接在图上进行标记,把进入队列的点标记为 str [ i ] [ j ] = ‘#’。另外如果你是用cin,cout别忘了加ios::sync_with_stdio(false);

③其实也不用把某种路径的长度都求出,然后再求出所有路径中的最小值。直接第一次到达终点时结束就可以了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define ll long long
#define lowbit(x) ((~x+1)&x)
using namespace std;
const int N = 1e3+5;
int mp[4*N][6*N];
char str[4*N][6*N];
int begin_x,begin_y;
int end_x,end_y;
int dir[7][2] = {{-2,0},{-1,3},{1,3},{2,0},{1,-3},{-1,-3}};
int t,n,m;
struct node {
    int x,y,dis;
}pos,temp;
queue<node>q;
// int vis[4*N][6*N];


int bfs() {
    int ans = 0x3f3f3f;
    pos.x = begin_x;
    pos.y = begin_y;
    pos.dis = 1;
    q.push(pos);
    // vis[pos.x][pos.y] = 1;
    str[pos.x][pos.y] = '#';
    while(!q.empty()) {
        node now = q.front();
        q.pop();
        if(now.x==end_x&&now.y==end_y) {
            ans = min(ans,now.dis);
            continue;
        }
        for(int i=0; i<6; i++) {
            int tx,ty;
            tx = now.x+dir[i][0];
            ty = now.y+dir[i][1];
            if(str[tx][ty]!='\\'&&str[tx][ty]!='/'&&str[tx][ty]!='-') {
                temp.x = now.x+(2*dir[i][0]);
                temp.y = now.y+(2*dir[i][1]);
                temp.dis = now.dis+1;
                if(str[temp.x][temp.y]!='#') {
                // if(vis[temp.x][temp.y]==0) {
                    // vis[temp.x][temp.y] = 1;
                    str[temp.x][temp.y] = '#';
                    q.push(temp);
                }
            }
        }
    }
    if(ans==0x3f3f3f) return -1;
    else return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--) {
        // memset(vis,0,sizeof(vis));
        int cnt=0;
        cin>>n>>m;
        n = 4*n+3;
        m = 6*m+3;
        cin.ignore();
        for(int i=0; i<n; i++) {
            cin.getline(str[i],m*n,'\n');
            int len = strlen(str[i]);
            for(int j=0; j<len; j++) {
                if(str[i][j]=='S') {
                    begin_x = i;
                    begin_y = j;
                }
                else if(str[i][j]=='T') {
                    end_x = i;
                    end_y = j;
                }
            }
        }
        cout<<bfs()<<endl;
    }
    return 0;
}

//1
//3 3
//   +---+       +---+
//  /     \     /     \
// +   p   +---+       +---+
//  \     n     \     /     \
//   +   +   S   +---+   T   +
//  /     \     /           /
// +       +---+       +   +
//  \           \     /     \
//   +---+       +---+       +
//  /                       /
// +       +---+       +   +
//  \                 /     \
//   +---+       +---+       +
//        \     /     \     /
//         +---+       +---+


// 1
// 1 1
//   +---+
//  /     \
// +       +---+
//  \           \
//   +   +   S   +
//        \     /
//         +---+
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值