题目描述
二货小易有一个W*H的网格盒子,网格的行编号为0~H-1,网格的列编号为0~W-1。每个格子至多可以放一块蛋糕,任意两块蛋糕的欧几里得距离不能等于2。
对于两个格子坐标(x1,y1),(x2,y2)的欧几里得距离为:
( (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2) ) 的算术平方根
小易想知道最多可以放多少块蛋糕在网格盒子里。
输入描述:
每组数组包含网格长宽W,H,用空格分割.(1 ≤ W、H ≤ 1000)
输出描述:
输出一个最多可以放的蛋糕数
示例1
输入
3 2
输出
4
思路1
使用vector<vector<int>>
定义一个二维数组,resize开辟空间并初始化,每个位置初始化为1,表示当蛋糕,a[i][j]位置放蛋糕,则可以标记处a[i][j+2] 和 a[i+2][j]位置不能放蛋糕,遍历一遍二维数组,标记处不能放蛋糕的位置,统计也就统计出了当蛋糕的位置数。
题解代码
#include <iostream>
#include <vector>
using namespace std;
int main(){
int W, H, count = 0;
cin >> W >> H;
vector<vector<int>> vv(W, vector<int>(H, 1));
// 直接暴力计算,默认所有蛋糕的位置标记成1,不能放的地方标记成0
for(int i = 0; i < W; ++i){
for(int j = 0; j < H; ++j){
if(vv[i][j]){
count++;
// 标记不能放蛋糕的位置
if ((i + 2) < W)
vv[i + 2][j] = 0;
if ((j + 2) < H)
vv[i][j + 2] = 0;
}
}
}
cout << count << endl;
return 0;
}
思路2
思路一完成后,根据下面的图,利用数学功底,得出来的特殊算法
题解代码:
// 默认所有蛋糕的位置标记成1,不能放的地方标记成0
// 1 1 0 0 1 1
// 1 1 0 0 1 1
// 0 0 1 1 0 0
// 0 0 1 1 0 0
#include <iostream>
using namespace std;
int main()
{
int a, b;
cin >> a >> b;
int x, y;
int suba = 4 - (a % 4 ? a % 4 : 4); // 长差 suba 为4的倍数
int subb = 4 - (b % 4 ? b % 4 : 4); // 宽差 subb 为4的倍数
x = a + suba; // 使 x 在加上suba后为4的倍数
y = b + subb; // 使 y 在加上subb后为4的倍数
int sum = x * y / 2; // 计算长宽都扩容至4的倍数后sum的大小
sum -= suba * (x / 2) + subb * (y / 2); // 减去增容的长与宽的一半,但这样会造成多减去蛋糕数量
if (suba == 0 || subb == 0) // 长或者宽只要有一个是4的倍数,经过上面算式后,可直接输出
{
//do nothing
}
else if (suba == 1 && subb == 1)
{
sum++; // 示例 长宽皆为3,
}
else if (suba == 1 || subb == 1)
{
sum += 2; // 示例 长3,宽2
}
else if (suba == 3 && subb == 3)
{
sum += 5; // 示例 长1,宽1
}
else
{
sum += 4;
}
cout << sum;
return 0;
}
代码生成图
如有不同见解,欢迎留言讨论~~