一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情
第十三届蓝桥杯省赛模拟赛第八题
试题:插头
题目描述
小蓝有一个插板,形状用一个 nm 的矩阵表示,0 表示板面,1 表示插孔。
小蓝还有一个插头,形状用一个 rc 的01矩阵表示,0 表示没有伸出的部分,1 表示伸出的部分,1 表示伸出的部分。插头伸出的部分必须插在插孔里面。
为了安全,插头插到面板上不能有任何部分超过插板边界(包括没有伸出的部分)。
插头和插板都不能旋转,也不能翻转,请求出插头插入插板的合理位置。
输入格式
输入的第一行包含两个整数n,m.
接下来 n 行,每行一个长度为 m 的01串,表示插板的形状。
接下来一行包含两个整数r ,c.
接下来r 行,每行一个长度为c的01串,表示插头的形状。
输出格式
如果插头没办法安全插入插板中,输出"NO". 否则输出两个数a ,b, 表示插头的第一行第一列对应插板的第a行第b列。如果有多种情况满足要求,输出a最小的方案,如果a最小的方案有多个,输出在a最小的前提下b最小的方案。
样例输入
3 4
0110
0000
0000
3 3
000
010
000
样例输出
NO
样例输入
4 7
1110100
1101111
0001111
0000011
2 3
111
011
样例输出
2 4
评测用例规模与约定
对于50%的评测用例,2<=n,m,r,c<=20. 对于所有评测用例 2<=n,m,r,c<=100.
思路分析
这道题看起来比较复杂,实际上暴力搜索也能求解,,枚举两个矩阵
时间复杂度为O(n^4),这是由于数据量比较小的缘故.两个矩阵的行列最大也只有100\
我的思路是枚举两轮
第一轮我们先从插板的左上角开始枚举,如图
然后第二轮就是枚举插头,把插头的左上角一个一个地和第一轮遍历区域配对,判断所有插头伸出部分是否都能插进插板,我是用一个ok函数进行判断,如果插头伸出部分插不进就不行,if (a[x+i][y+j] == '0' && b[i][j] == '1') 就不行。
值得注意的一点是,如果插头能插进去,最后要输出的是插头的左上角,要加上1,因为我开的数组是从0开始记录的。
AC代码
#include<iostream>
using namespace std;
int n, m,r,c;
char a[100][100], b[100][100];
bool ok(int x, int y)
{
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
{
if (a[x+i][y+j] == '0' && b[i][j] == '1')
return 0;
}
return 1;
}
int main()
{
cin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> a[i][j];
cin >> r >> c;
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
cin >> b[i][j];
for (int x = 0; x < n - r; x++)
for (int y = 0; y < m - c; y++)
{
if (ok(x, y))//判断是否能
{
cout << x + 1 << ' ' << y + 1;
return 0;
}
}
cout << "NO";
return 0;
}
总结
这道题咋一看复杂,但细心审题就能发现暴力枚举也能解决。
以后我刷题会少刷一些简单题,尽量系统化刷题,不再那么追求刷题量了。