藍橋杯2020年4月模擬賽
問題描述
小明和朋友們一起去郊外植樹,他們帶了一些在自己實驗室精心研究出的小樹苗。
小明和朋友們一共有n個人,他們經過精心挑選,在一塊空地上每個人挑選了一個適合植樹的位置,總共n個。他們準備把自己帶的樹苗都植下去。
然而,他們遇到了一個困難:有的樹苗比較大,而有的位置挨太近,導致兩棵樹植下去後會撞在一起。
他們將樹看成一個圓,圓心在他們找的位置上。如果兩棵樹對應的圓相交,這兩棵樹就不適合同時植下(相切不受影響) ,稱爲兩棵樹衝突。
小明和朋友們決定先合計合計,只將其中的一部分樹植下去,保證沒有互相沖突的樹。他們同時希望這些樹所能覆蓋的面積和(圓面積和)最大。
輸入格式
輸入的第一行包含一個整數n ,表示人數,即準備植樹的位置數。
接下來n行,每行三個整數x,y,r,表示一棵樹在空地上的橫、縱座標和半徑。
輸出格式
輸出一行包含一個整數,表示在不衝突下可以植樹的面積和。於每棵樹的面積都是圓周率的整數倍,請輸出答案除以圓周率後的值(應當是一個整數)。
樣例輸入
6
1 1 2
1 4 2
1 7 2
4 1 2
4 4 2
4 7 2
樣例輸出
12
評測用例規模與約定
對於30%的評測用例,1<=n<=10;
對於60%的評測用例,1<=n<=20;
對於所有評測用例,1<=n<=30,0<=x,y<=1000,
1 <= r <=1000。
代碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
/*
6
1 1 2
1 4 2
1 7 2
4 1 2
4 4 2
4 7 2
*/
using namespace std;
const int MAXN = 1000 + 10;
int n;
int x[MAXN], y[MAXN], r[MAXN];
double pi = acos(-1);
bool vis[MAXN];
int ans = 0;
bool cal(int i)
{
for(int j = 0; j < n; j ++)
{
if(i != j && vis[j])
{
int dis = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);
if(dis < (r[i] + r[j]) * (r[i] + r[j])) return false;
}
}
return true;
}
void dfs(int step, int sum)
{
if(step == n)
{
ans = max(ans, sum);
return;
}
for(int i = 0; i < n; i ++)
{
if(!vis[i])
{
int tmp = r[i];
if(!cal(i)) r[i] = 0;
vis[i] = true;
dfs(step + 1, sum + r[i] * r[i]);
vis[i] = false;
r[i] = tmp;
}
}
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; i ++)
scanf("%d%d%d", &x[i], &y[i], &r[i]);
dfs(0, 0);
printf("%d", ans);
return 0;
}