题意:
给出墙的四面的边长,给出 所有 挖掘机的作业半径以及位置。
其中墙的几何中心就是坐标的原点。
需要特别注意的是:挖掘机覆盖的是“墙的边长上的中点”
最后要求的是给出可以覆盖这四个点最少的挖掘机的数目。
解题思路:
这个题目如果通过枚举就是2的n次方,其中n为挖掘机数目。因为每个挖掘机有两个状态:用 或者 不用。所以是指数级,会爆。
考虑另一种暴力求解方法:
考虑题目中答案只有几种情况?
5种。
0.没有挖掘机可以覆盖所有点,输出0
1.能否用一台挖掘机覆盖所有点,如果可以输出1
2.能否用两台挖掘机覆盖所有点,如果可以输出2
3.能否用三台挖掘机覆盖所有点,如果可以输出3
4.直接输出4。思考为什么?
这样复杂度变为了O(n^3)明显改善了。
代码实现:
(一定要看完该说明)
1.需要特别说明的是:每个挖掘机都有一个数组标记该挖掘机覆盖了那几个点,此外读者可以想到:如果在读取挖掘机信息的时候经过计算该挖掘机将所有的点都覆盖那么这时候输出1就可以。因为只要这一台就够了。
2.同时数组bool AllTest [4];是用来记录这四个点的被覆盖的情况,
考虑这样一种情况:
如果读取完所有的挖掘机发现四个点没有全部被覆盖 ,这时候输出0就好。
3.最后是使用for循环进行遍历。遍历一定要全部遍历,不可以中途退出。需要有一个int用来存放所需挖掘机的数目,应用来比较大小,因为有可能在循环开始的时候发现3台机器可以覆盖,此时记录3,但是后来又发现1台机器就足够了,此时记录1。那么最后输出的记录是1.
#include <cstdio>
#include <iostream>
#include <cmath>
#define EPS = 0.00000001
using namespace std;
int n;
struct Point
{
double x = 0, y = 0;
};
Point u, d, l, r;
struct Crane
{
double x , y , r_pow;
int name, covernum = 0;
bool cover[4];// u p l r
};
Crane con[31];
bool AllTest [4];
// void out(Crane a) {
// cout << "the crane:" << a.name << " ---- " << a.x << " " << a.y << " " << a.covernum << endl;
// }
// void out_point() {
// cout << "u" << u.x << " " << u.y << endl;
// cout << "d" << d.x << " " << d.y << endl;
// cout << "l" << l.x << " " << l.y << endl;
// cout << "r" << r.x << " " << r.y << endl;
// }
void check(Crane &a) {
if (a.r_pow >= pow((a.x - u.x), 2) + pow((a.y - u.y), 2) )
{
a.cover[0] = true;
AllTest[0] = true;
a.covernum += 1;
}
if (a.r_pow >= pow((a.x - d.x), 2) + pow((a.y - d.y), 2) )
{
a.cover[1] = true;
AllTest[1] = true;
a.covernum += 1;
}
if (pow((a.x - l.x), 2) + pow((a.y - l.y), 2) <= a.r_pow )
{
a.cover[2] = true;
AllTest[2] = true;
a.covernum += 1;
}
if (pow((a.x - r.x), 2) + pow((a.y - r.y), 2) <= a.r_pow )
{
a.cover[3] = true;
AllTest[3] = true;
a.covernum += 1;
}
}
int combine_check(Crane a , Crane b) {
int res = 0;
for (int i = 0; i < 4; i++)
{
if (a.cover[i] || b.cover[i])
res += 1;
}
return res;
}
int three_check(Crane a , Crane b , Crane c) {
int res = 0;
for (int i = 0; i < 4; i++)
{
if (a.cover[i] || b.cover[i] || c.cover[i])
{
res++;
}
}
return res;
}
int main(int argc, char const *argv[])
{
double len, w, radis;
scanf("%lf%lf%d%lf", &len, &w, &n, &radis);
//(x,y)=(−ℓ/2,0),(ℓ/2,0),(0,−w/2),(0,w/2)
u.y = w / 2;
d.y = -w / 2;
l.x = -len / 2;
r.x = len / 2;
// out_point();
double rr = pow( radis,2);
for (int i = 0; i < n; i++)
{
scanf("%lf %lf", &con[i].x, &con[i].y);
con[i].r_pow = rr;
con[i].name = i;
}
for (int i = 0; i < n; ++i)
{
check(con[i]);
// printf("->%d\n", con[i].covernum );
if (con[i].covernum == 4)
{
printf("1");
return 0;
}
}
if ((!AllTest[0]) || (!AllTest[1]) || (!AllTest[2]) || (!AllTest[3]))
{
printf("Impossible\n");
return 0;
}
// for (int i = 0; i < n; i++)
// {
// out (con[i]);
// }
int temp = 4;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (combine_check (con[i], con[j]) == 4&& temp > 2)
{
temp =2;
}
for (int k = j + 1; k < n; k++)
{
if (three_check (con[i], con[j], con[k]) == 4&&temp>3)
{
temp = 3;
}
}
}
}
printf("%d",temp);
return 0;
}