1. 题目来源
链接:不要二
来源:牛客网
2. 题目说明
小易有一个W*H的网格盒子,网格的行编号为0 ~ H-1,网格的列编号为0 ~ W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。
对于两个格子坐标
(
x
1
,
y
1
)
、
(
x
2
,
y
2
)
(x_1,y_1)、(x_2,y_2)
(x1,y1)、(x2,y2)的欧几里得距离为:
(
x
1
−
x
2
)
2
+
(
y
1
−
y
2
)
2
\sqrt{( x_1-x_2)^2 +(y_1-y_2)^2}
(x1−x2)2+(y1−y2)2
小易想知道最多可以放多少块蛋糕在网格盒子里。
输入描述:
每组数组包含网格长宽W,H,用空格分割.(1 ≤ W、H ≤ 1000)
输出描述:
输出一个最多可以放的蛋糕数
示例1
输入
3 2
输出
4
3. 题目解析
本题看起来很难没有思路,实际是一个中等难度的题。貌似是一个往年网易的笔试题,可以看到大厂的题的难度。
本题的重点是要读懂题意,并且需要多读两遍,才能读懂,本题本质就是在二维数组中每个坐标去放蛋糕,一个坐标位置放了蛋糕,跟他欧几里得距离为2的位置不能放蛋糕,这个就是关键点。对于两个格子坐标
(
x
1
,
y
1
)
、
(
x
2
,
y
2
)
{( x_1,y_1) 、(x_2,y_2)}
(x1,y1)、(x2,y2) 的欧几里得距离为:
(
x
1
−
x
2
)
2
+
(
y
1
−
y
2
)
2
\sqrt{( x_1-x_2)^2 +(y_1-y_2)^2}
(x1−x2)2+(y1−y2)2 也就是说:如果(x1,y1)放了蛋糕,则满足
(
x
1
−
x
2
)
2
+
(
y
1
−
y
2
)
2
=
4
\sqrt{( x_1-x_2)^2 +(y_1-y_2)^2}= 4
(x1−x2)2+(y1−y2)2=4 的
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2)不能放蛋糕。
(
x
1
−
x
2
)
2
+
(
y
1
−
y
2
)
2
=
4
\sqrt{( x_1-x_2)^2 +(y_1-y_2)^2}= 4
(x1−x2)2+(y1−y2)2=4 看起来是一个无解的表达式。
但是可以进行加法表达式分解:
1+3=4
3+1=4
2+2=4
0+4=4
4+0=4
仔细分析前三个表达式是不可能的,因为
(
x
2
,
y
2
)
2
(x_2,y_2)^2
(x2,y2)2表达式结果不能等于2或3。 也就是说
(
x
1
−
x
2
)
2
、
(
y
1
−
y
2
)
2
( x_1-x_2)^2、 (y_1-y_2)^2
(x1−x2)2、(y1−y2)2 两个表达式一个等于0,一个等于4.
可以看出:假设放蛋糕的位置是
(
x
1
,
y
1
)
(x_1,y_1)
(x1,y1),则不能放蛋糕的位置
(
x
2
,
y
2
)
(x_2,y_2)
(x2,y2),满足两种情况
x
1
=
x
2
x_1=x_2
x1=x2,
y
1
−
y
2
=
2
y_1-y_2=2
y1−y2=2或者
x
1
−
x
2
=
2
x_1-x_2=2
x1−x2=2,
y
1
=
y
2
y_1=y_2
y1=y2。将这个复杂的问题进行分析之后变的清晰易懂了,“题感”的积累是必要的。
仔细理解了上面的题目解读,本题就非常简单了,使用vector<vector < int >>定义一个二维数组,resize开辟空间并初始化,每个位置初始化为1,表示当蛋糕,a[i][j]位置放蛋糕,则标记处a[i][j+2]和a[i+2][j]位置不能放蛋糕,遍历一遍二维数组,标记处不能放蛋糕的位置,就统计出了最大放蛋糕的位置数。
4. 代码展示
#include <bits/stdc++.h>
using namespace std;
int main() {
int w, h, res = 0;
cin >> w >> h;
vector<vector<int>> a;
a.resize(w);
for (auto& e : a)
e.resize(h, 1);
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
if (a[i][j] == 1) {
res++;
// 标记不能放蛋糕的位置
if ((i + 2) < w)
a[i + 2][j] = 0;
if ((j + 2) < h)
a[i][j + 2] = 0;
}
}
}
cout << res;
return 0;
}