标题:不要二 | 时间限制:1秒 | 内存限制:32768K
二货小易有一个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)
输出描述: 输出一个最多可以放的蛋糕数
--NOWCODER.COM 牛客网·互联网名企笔试/面试题库
示例1:
输入 3 2
输出 4
思路:这道题的就是让两个坐标的差值和不能为2,由此可画出以下的一张表,红色代表可以放蛋糕的坐标。
解法1:复杂度O(n^2)
做一张二维的表,将每一行每一列的值填进去,1代表可以放蛋糕,0代表不可以。最后统计出1的个数即可。
1 1 0 0 1 1 0 0
1 1 0 0 1 1 0 0
0 0 1 1 0 0 1 1
0 0 1 1 0 0 1 1
#include<iostream>
#include<vector>
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;
}
解法2:复杂度O(1)
由表中可以得出一个很简单的规律:当横纵坐标为4的倍数时,可以放的蛋糕数为总格子数的一半,若不是4的倍数,将其扩展为离他最近的4的倍数,比如5—>8 , 7—>8,看图:下面就以5,7为例:
红色代表可以放的位置,蓝色代表纵坐标将要扩展后可放蛋糕的位置,
黄色代表横坐标扩展后可放蛋糕的位置,蓝色代表横纵坐标扩展后可放蛋糕的位置的重叠区域。
x----横坐标需要扩展的长度(3),y----纵坐标需要扩展的长度(1)
xx----横坐标扩展后的长度(8),yy-----纵坐标扩展后的长度(8)
由此可以有:
最终可放蛋糕的位置数 =
(扩展后的横坐标 *扩展后的纵坐标)/ 2
-((横坐标需要扩展的长度 * 纵坐标扩展后的长度)+(纵坐标需要扩展的长度 * 横坐标扩展后的长度))/2 + (重叠区域的可放蛋糕的格子数)
= (xx*yy)/2 - ((x*yy)+(y*xx))/2 + 重叠区域的可放蛋糕的格子数
= 32 - 16 + 2
= 18
最难的地方就是如何求得重合部分的可放蛋糕的格子数。
以下为求重合部分的可放蛋糕的格子数的几种情况,列举出即可:
1.当横纵坐标某一个不需扩展,或两个都不需扩展时,不存在重合区域,直接减去扩展超出那部分即可。
2、当纵横坐标需要扩展的长度都在1—2之间时,要加上的重叠区域大小为x*y。
3、纵横坐标都扩展3时,重叠区域就变成了5。
4、纵横坐标扩展长度一个为1,另一个为3时,重叠区域固定为2。
5、最后一种情况:横纵坐标扩展长度分别为2和3时,重叠区域固定为4。
代码实现:
int main()//O(1)算法
{
int W, H;
cin >> W >> H;
int x = W;
int y = H;
x = (x % 4 == 0 ? 0 : (4 - (x % 4)));//需要扩展多少坐标数
y = (y % 4 == 0 ? 0 : (4 - (y % 4)));
int xx = x + W;//扩展后的纵横坐标,为4的倍数
int yy = y + H;
int block = (xx * yy) / 2;//所求的格子数为纵横坐标乘积的一般,先减去扩展的那部分,最后加上扩展重合的部分
block -= (x * yy + y * xx) / 2;
if (x == 0 || y == 0)//没有扩展,无需减去重叠区域
{
//do nothing
}
else if (x <= 2 && y <= 2)//x y = (1,2)
{
block += x * y;
}
else if (x == 1 && y == 3 || x == 3 && y == 1)//x y =(1,3)
{
block += 2;
}
else if (x == 3 && y == 3)
{
block += 5;
}
else//x==2/3 && y==3/2
{
block += 4;
}
cout << block << endl;
system("pause");
return 0;
}