守护雅典娜
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 324 Accepted Submission(s): 91
Problem Description
许多塔防游戏都是以经典的“守护雅典娜”为原型的。玩家需要建立各种防御工具来阻止怪物接近我们的女神——雅典娜。
这里,我们可以建造的防御工具只有标准圆形状的防御墙,建立在雅典娜与怪物出生点之间的防御墙数目越多,胜利的希望就越大。这里,将问题简化到一个二维坐标系里,并且假设雅典娜的坐标为原点(0, 0),怪物出生点的坐标为(X, Y)。有N个给定圆心坐标与半径的防御墙可以供玩家选择建立,但要保证所有的圆都不发生相切或相交的情况。注意这些雅典娜位置与怪物出生点位置也不能在墙壁的边缘,即表示防御墙的圆上。点的面积与墙的厚度都很小,可以忽略不计。
记住,在游戏开始之后,怪物可以沿着任何轨迹,选择突破最少的圆形防御墙来到雅典娜的身边,而一个防御墙一旦被突破,它就会失去保护作用。所以,你的方案必须足够优秀。为了守护女神,快去找出最优的建设方案吧!
这里,我们可以建造的防御工具只有标准圆形状的防御墙,建立在雅典娜与怪物出生点之间的防御墙数目越多,胜利的希望就越大。这里,将问题简化到一个二维坐标系里,并且假设雅典娜的坐标为原点(0, 0),怪物出生点的坐标为(X, Y)。有N个给定圆心坐标与半径的防御墙可以供玩家选择建立,但要保证所有的圆都不发生相切或相交的情况。注意这些雅典娜位置与怪物出生点位置也不能在墙壁的边缘,即表示防御墙的圆上。点的面积与墙的厚度都很小,可以忽略不计。
记住,在游戏开始之后,怪物可以沿着任何轨迹,选择突破最少的圆形防御墙来到雅典娜的身边,而一个防御墙一旦被突破,它就会失去保护作用。所以,你的方案必须足够优秀。为了守护女神,快去找出最优的建设方案吧!
Input
输入第一行为T,表示有T组测试数据。
每组数据以三个整数N,X,Y开始,接下去的N行每行包括三个整数Xi,Yi,Ri,表示一个可以选择的圆心为(Xi, Yi)半径为Ri的防御墙。
[Technical Specification]
1. 1 <= T <= 100
2. 1 <= N <= 1000
3. 1 <= Ri <= 10 000
4. -10 000 <= X, Y, Xi, Yi <= 10 000,坐标不会相同
每组数据以三个整数N,X,Y开始,接下去的N行每行包括三个整数Xi,Yi,Ri,表示一个可以选择的圆心为(Xi, Yi)半径为Ri的防御墙。
[Technical Specification]
1. 1 <= T <= 100
2. 1 <= N <= 1000
3. 1 <= Ri <= 10 000
4. -10 000 <= X, Y, Xi, Yi <= 10 000,坐标不会相同
Output
对每组数据,先输出为第几组数据,然后输出能够间隔在雅典娜与怪物出生点之间最多的防御墙数目。
Sample Input
3
1 5 5
1 0 2
1 5 5
1 0 9
3 5 5
1 0 2
4 5 2
2 0 6
Sample Output
Case 1: 1
Case 2: 0
Case 3: 2
Source
Recommend
liuyiding
很早就做了的这题,思路都对,就是写错一个地方,今天终于找到错误了。
先找出分别包含两个点的圆,然后DP求解
//============================================================================ // Name : B.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <map> #include <vector> #include <set> #include <queue> #include <string> #include <math.h> using namespace std; const int MAXN=1010; struct Node { int x,y; int r; }; bool cmp(Node a,Node b) { return a.r<b.r; } int dis2(Node a,Node b) { return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Node node[MAXN]; Node node1[MAXN]; Node node2[MAXN]; int dp1[MAXN]; int dp2[MAXN]; int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int T; int n; int iCase=0; Node st; st.x=0;st.y=0; Node ed; scanf("%d",&T); while(T--) { iCase++; printf("Case %d: ",iCase); scanf("%d",&n); scanf("%d%d",&ed.x,&ed.y); int t1=0; int t2=0; for(int i=0;i<n;i++) { scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].r); int d1=dis2(st,node[i]); int d2=dis2(ed,node[i]); if(d1==node[i].r*node[i].r||d2==node[i].r*node[i].r) continue; if(d1<node[i].r*node[i].r&&d2<node[i].r*node[i].r)continue; if(d1>node[i].r*node[i].r&&d2>node[i].r*node[i].r)continue; if(d1<node[i].r*node[i].r) { node1[t1++]=node[i]; } else node2[t2++]=node[i]; } sort(node1,node1+t1,cmp); sort(node2,node2+t2,cmp); int ans1=0,ans2=0; for(int i=0;i<t1;i++) { dp1[i]=1; for(int j=0;j<i;j++) { int d=dis2(node1[i],node1[j]); if(node1[i].r>node1[j].r && d<(node1[i].r-node1[j].r)*(node1[i].r-node1[j].r)) dp1[i]=max(dp1[i],dp1[j]+1); } ans1=max(ans1,dp1[i]); } for(int i=0;i<t2;i++) { dp2[i]=1; for(int j=0;j<i;j++) { int d=dis2(node2[i],node2[j]); if( node2[i].r>node2[j].r && d<(node2[i].r-node2[j].r)*(node2[i].r-node2[j].r)) dp2[i]=max(dp2[i],dp2[j]+1); } ans2=max(ans2,dp2[i]); } int ans=max(ans1,ans2); for(int i=0;i<t1;i++) for(int j=0;j<t2;j++) { int d1=dis2(node1[i],node2[j]); if(d1>(node1[i].r+node2[j].r)*(node1[i].r+node2[j].r)) ans=max(ans,dp1[i]+dp2[j]); } printf("%d ",ans); } return 0; }