POJ3178 计算几何+DP
1 //一些点一些圆,过圆不能连线,相邻点不能连线,问最多连几条线 2 //计算几何模板+区间dp 3 //关键是判断圆和线段是否相交 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #define N 500 8 #define ll long long 9 #define sqr(x) ((x)*(x)) 10 using namespace std; 11 bool ok[N][N]; 12 ll n,m,r,f[N][N]; 13 struct poi 14 { 15 ll x,y; 16 poi(ll X,ll Y) 17 { 18 x=X;y=Y; 19 } 20 poi() 21 { 22 } 23 } p[N],q[N]; 24 ll cro(poi a,poi b) 25 { 26 return (a.x*b.y-a.y*b.x); 27 } 28 ll dot(poi a,poi b) 29 { 30 return a.x*b.x+a.y*b.y; 31 } 32 poi tr(poi a,poi b) 33 { 34 return poi(a.x-b.x,a.y-b.y); 35 } 36 double dis(poi a,poi b) 37 { 38 return sqrt((double)(sqr(a.x-b.x)+sqr(a.y-b.y))); 39 } 40 bool cmp(poi a,poi b) 41 { 42 return (a.x<b.x)||(a.x==b.x && a.y<b.y); 43 } 44 bool cmp2(poi a,poi b) 45 { 46 return cro(tr(a,p[1]),tr(b,p[1]))>0; 47 } 48 bool check(poi a,poi b) 49 { 50 double C=dis(a,b); 51 for(int i=1;i<=m;i++) 52 { 53 double A=dis(q[i],a); 54 double B=dis(q[i],b); 55 double COSA=(B*B+C*C-A*A)/(2*B*C); 56 double COSB=(A*A+C*C-B*B)/(2*A*C); 57 if(COSA<1e-10||COSB<1e-10){ 58 if(A<1.0*r+1e-10||B<1.0*r+1e-10)return 0; 59 else continue; 60 } 61 double SINA=sqrt(1-COSA*COSA); 62 double H=B*SINA; 63 if(H<1.0*r+1e-10)return 0; 64 } 65 return 1; 66 } 67 int main() 68 { 69 scanf("%d%d%d",&n,&m,&r); 70 for(int i=1;i<=n;i++) 71 scanf("%d%d",&p[i].x,&p[i].y); 72 sort(p+1,p+1+n,cmp); 73 sort(p+2,p+1+n,cmp2); 74 for(int i=1;i<=m;i++) 75 scanf("%d%d",&q[i].x,&q[i].y); 76 for(int i=1;i<=n;i++) 77 for(int j=i+2;j<=n;j++) 78 if(i!=1 || j!=n) 79 ok[i][j]=check(p[i],p[j]); 80 for(int len=2;len<=n;len++) 81 for(int start=1;start<=n;start++){ 82 ll end=start+len; 83 for(int k=start+1;k<min(end,n);k++) 84 f[start][end]=max(f[start][end],f[start][k]+f[k][end]); 85 f[start][end]+=ok[start][end]; 86 } 87 printf("%d\n",f[1][n]); 88 }