总时间限制: 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;
}