试题编号: 202206-2
试题名称: 寻宝!大冒险!
时间限制: 500ms
内存限制: 512.0MB
需要注意的细节:
- 数据范围
地图a如果用数组存储,范围过大,容易溢出,尽量不存储或用其他方式,如vector。
藏宝图b范围较小,可以用数组直接存储。
- 数组b的输入顺序
- 越界问题
由此可知,可以认为每颗树都可以作为藏宝图的左下角位置。
依次遍历所有的树并判断是否可以为藏宝位置。
简单的判断方式:比较矩阵内的所有点的bool值是否相等。
n
(表示输入的点数)、L
(表示平面的边长)、S
(表示模式的边长)和 ans
(用于存储匹配的次数)。这些变量的类型是 ll
,即长整型(long long
),以确保能够处理较大的数值。
int main(){
ll n,L,S,ans=0;
cin>>n>>L>>S;
接下来,程序定义了一个 map
容器 mp
,用于存储输入的点坐标,并将其标记为 true
。同时,定义了一个二维布尔数组 b
,用于存储模式的布尔矩阵。
map<pair<ll,ll>,bool>mp;
bool b[55][55];
然后,程序通过循环读取 n
个点的坐标,并将这些坐标存储在 map
容器 mp
中。
for(ll i=0;i<n;i++){
ll x,y;
cin>>x>>y;
mp[{x,y}]=1;
}
接下来,程序读取模式矩阵 b
的值。注意,这里是从 S+1
到 1
进行读取,以便将模式矩阵倒置存储。
for(ll i=S+1;i>=1;i--)
for(ll j=1;j<=S+1;j++)
cin>>b[i][j];
然后,程序遍历 map
容器 mp
中的每个点,并检查以该点为左下角的 S+1
x S+1
区域是否与模式矩阵 b
匹配。具体来说,程序通过嵌套循环遍历模式矩阵的每个元素,并检查对应的平面坐标是否在 map
容器 mp
中存在且值相同。如果有任何一个元素不匹配,则标记 flag
为 false
并退出循环。
for(auto it:mp){
ll x=it.first.first,y=it.first.second;
bool flag=true;
for (ll i = 0; i <= S; i++)
{
for(ll j=0;j<=S;j++){
ll xx=x+i,yy=y+j;
if(xx>L||yy>L||mp[{xx,yy}]!=b[i+1][j+1]){
flag=false;
break;
}
}
if(!flag) break;
}
if(flag) ans++;
}
最后,程序输出匹配的次数 ans
。
参考代码
#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
int main() {
ll n, L, S, ans = 0;
// 读取输入的 n, L, S
cin >> n >> L >> S;
// 定义一个 map 来存储点的坐标
map<pair<ll, ll>, bool> mp;
// 定义一个二维数组来存储模板
bool b[55][55];
// 读取 n 个点的坐标并存储在 map 中
for (ll i = 0; i < n; i++) {
ll x, y;
cin >> x >> y;
mp[{x, y}] = 1;
}
// 读取模板的值,注意模板是倒序读取的
for (ll i = S + 1; i >= 1; i--)
for (ll j = 1; j <= S + 1; j++)
cin >> b[i][j];
// 遍历 map 中的每个点
for (auto it : mp) {
ll x = it.first.first, y = it.first.second;
bool flag = true;
// 检查模板是否匹配
for (ll i = 0; i <= S; i++) {
for (ll j = 0; j <= S; j++) {
ll xx = x + i, yy = y + j;
// 如果超出边界或者不匹配模板,设置 flag 为 false 并跳出循环
if (xx > L || yy > L || mp[{xx, yy}] != b[i + 1][j + 1]) {
flag = false;
break;
}
}
if (!flag) break;
}
// 如果模板匹配,计数器加一
if (flag) ans++;
}
// 输出结果
cout << ans;
return 0;
}