比赛的时候WA得一塌糊涂~~原因!..读题粗心了!!上一题的输出是Case #1: 0 , 而本题居然是Case 1: 1 ... 同一套题..神坑...
思路很简单了..能产生防御效果的..无非是能包住雅典娜或者包住怪兽的圆..而当一个圆同时包住了雅典娜和怪兽..同样也没有了防御效果..
考虑N个圆包住一个点并且互不相交/切能取最多圆的个数问题..用dp解决..dp顺序按照圆的半径从小到大(很明显,一个圆要包住另一个圆,其半径必须比它大)...
分别算出了包住雅典娜dp[0][],包住怪兽的dp值dp[1][]..再找两个不相冲突能得到的最大圆个数...既是答案..
Program:
#include<iostream>
#include<stdio.h>
#include<cmath>
#include<string.h>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#define pi acos(-1.0)
#define ll long long
#define oo 1000000000
#define MAXN 1005
using namespace std;
struct node
{
int x,y,r;
}a[MAXN];
int n,x,y,sum[2][MAXN];
bool cmp(node a,node b)
{
return a.r<b.r;
}
bool ok(node a,node b) // 判断两个圆是否不相交/切
{
int d,r1,r2;
d=(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
r1=a.r-b.r; r2=a.r+b.r;
if (r1*r1<=d && d<=r2*r2) return false;
return true;
}
int main()
{
int T,t,i,j,ans;
scanf("%d",&T);
for (t=1;t<=T;t++)
{
scanf("%d%d%d",&n,&x,&y);
for (i=1;i<=n;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].r);
sort(a+1,a+1+n,cmp);
ans=0;
memset(sum,0,sizeof(sum));
for (i=1;i<=n;i++)
{
if (a[i].x*a[i].x+a[i].y*a[i].y>=a[i].r*a[i].r ||
(a[i].x-x)*(a[i].x-x)+(a[i].y-y)*(a[i].y-y)<=a[i].r*a[i].r ) //找出包住雅典娜,但又包不住怪兽的圆
continue;
for (j=1;j<i;j++)
if (sum[0][i]<sum[0][j] && ok(a[i],a[j]))
sum[0][i]=sum[0][j];
sum[0][i]++;
ans=max(ans,sum[0][i]);
}
for (i=1;i<=n;i++)
{
if (a[i].x*a[i].x+a[i].y*a[i].y<=a[i].r*a[i].r ||
(a[i].x-x)*(a[i].x-x)+(a[i].y-y)*(a[i].y-y)>=a[i].r*a[i].r ) //找出包住怪兽,但又包不住雅典娜的圆
continue;
for (j=1;j<i;j++)
if (sum[1][i]<sum[1][j] && ok(a[i],a[j]))
sum[1][i]=sum[1][j];
sum[1][j]++;
ans=max(ans,sum[1][i]);
}
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if (ans<sum[0][i]+sum[1][j] && ok(a[i],a[j])) ans=sum[0][i]+sum[1][j]; // 合并两个结果
printf("Case %d: %d\n",t,ans);
}
return 0;
}