11I:变换的迷宫(bfs迷宫问题)

 

总时间限制: 1000ms

内存限制: 10000kB

描述

爱好探险的你,找到一座装满了宝藏的迷宫的入口,你看到入口的大门上有一个边长为s的正方形的大锁,旁边散落着n块正方形的金属小片,你意识到锁的钥匙,即是用这n小块,拼成大门上的正方形,你想知道是否能拼成这把钥匙打开迷宫的大门。

输入

输入包含多组数组,第一行是一个整数t(1 <= t <= 10),表示有t组数据。接下里每组数组包含整数s,即锁的边长,整数n(1 <= n <= 16),即金属小片的数量,接下来n个整数,分别是各个小片的边长ci(1 <= ci <= 10)。

输出

每组数据输出一行,输出“YES"或者"NO",表示是否可以打开大门。

样例输入

2
4 8 1 1 1 1 1 3 1 1
5 6 3 3 2 1 1 1

样例输出

YES
NO
/*
题型:bfs迷宫问题
难点:如何剪枝,关键还是那一点,如何尽可能简单地定义一个状态,使得它能唯一地确定结果。剪枝就是在通过检测中央的状态来避免走重复的路
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define _for(i,a,b) for(int i = (a); i < (b); ++i)
#define _rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define _zero(x) memset(x, 0, sizeof(x))
#define _init(x, v) memset(x, v, sizeof(x))
const int di[] = {0, 1, 0, -1}, dj[] = {1, 0, -1, 0};

int R, C, K;
char a[105][105];
bool vis[105][105][15];

struct node{
    int i, j, t;
};

queue<node> q;

void in(){
    _zero(vis);
    while(!q.empty()) q.pop();

    cin >> R >> C >> K;
    _for(i, 0, R) _for(j, 0, C){
        cin >> a[i][j];
        if(a[i][j] == 'S'){
            vis[i][j][0] = 0;
            q.push({i, j, 0});
        }
    }
}

bool inMap(int i, int j){
    return i >= 0 && j >= 0 && i < R && j < C;
}

int bfs(){
    while(!q.empty()){
        node s = q.front();
        q.pop();

        for(int k = 0; k < 4; ++k){
            int ii = s.i + di[k], jj = s.j + dj[k], tt = s.t+1;
            if(a[ii][jj] == 'E') return tt;
            if(!inMap(ii, jj)) continue;
            if(a[ii][jj] == '#' && tt % K != 0) continue;
            if(vis[ii][jj][tt%K]) continue;

            vis[ii][jj][tt%K] = 1;
            q.push({ii, jj, tt});
        }
    }
    return -1;
}

int main(){
    int T; cin >> T;
    while(T--){
        in();
        int ans = bfs();
        if(ans == -1) cout << "Oop!" << endl;
        else cout << ans << endl;
    }
    system("pause");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值