HDU 6603 Azshara's deep sea(凸包+区间DP)

由于题目要求,首先维护出一个凸包,然后在凸包上寻找点对关系,用rel[i][j]表示i点和j点之间是否可以连线,又由于维护出来的凸包上的点的个数不多,可以直接枚举点对并枚举所有圆,判断两点直线和圆是否相离,由于维护出来的凸包已经按照逆时针排序,又要满足两两线段不相交,最后就变成了求最大不相交线段个数,但是可以包含(2-5线段可以包含3-4,但是不能选择3-6),然后考虑区间DP去枚举所有情况,设dp[s][t]表示起点在s终点在t之间的区间内的最大不相交线段个数,枚举终点和起点,再枚举起点到终点内的点i,由于可以包含,则转移为dp[s][t]=max(dp[s][t],dp[s][i]+rel[s%n][t%n]),最后查询答案枚举所有长度为n的区间的最值即可。

  1 //        ——By DD_BOND
  2 
  3 //#include<bits/stdc++.h>
  4 //#include<unordered_map>
  5 //#include<unordered_set>
  6 #include<functional>
  7 #include<algorithm>
  8 #include<iostream>
  9 //#include<ext/rope>
 10 #include<iomanip>
 11 #include<climits>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<cstddef>
 15 #include<cstdio>
 16 #include<memory>
 17 #include<vector>
 18 #include<cctype>
 19 #include<string>
 20 #include<cmath>
 21 #include<queue>
 22 #include<deque>
 23 #include<ctime>
 24 #include<stack>
 25 #include<map>
 26 #include<set>
 27 
 28 #define fi first
 29 #define se second
 30 #define pb push_back
 31 
 32 typedef long long ll;
 33 
 34 using namespace std;
 35 
 36 const int MAXN=1e3+10;
 37 const double eps=1e-10;
 38 const double pi=acos(-1.0);
 39 const ll INF=0x3f3f3f3f3f3f3f3f;
 40 
 41 inline int dcmp(double x){
 42     if(fabs(x)<eps)    return 0;
 43     return (x>0? 1: -1);
 44 }
 45 
 46 inline double sqr(double x){ return x*x; }
 47 
 48 struct Point{
 49     double x,y;
 50     Point(){ x=0,y=0; }
 51     Point(double _x,double _y):x(_x),y(_y){}
 52     void input(){ scanf("%lf%lf",&x,&y); }
 53     void output(){ printf("%.2f %.2f\n",x,y); }
 54     friend istream &operator >>(istream &os,Point &b){
 55         os>>b.x>>b.y;
 56         return os;
 57     }
 58     friend ostream &operator <<(ostream &os,Point &b){
 59         os<<b.x<<' '<<b.y;
 60         return os;
 61     }
 62     bool operator ==(const Point &b)const{
 63         return (dcmp(x-b.x)==0&&dcmp(y-b.y)==0);
 64     }
 65     bool operator !=(const Point &b)const{
 66         return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0));
 67     }
 68     bool operator <(const Point &b)const{
 69         return (dcmp(x-b.x)==0? dcmp(y-b.y)<0 : x<b.x);
 70     }
 71     double operator ^(const Point &b)const{        //叉积
 72         return x*b.y-y*b.x;
 73     }
 74     double operator *(const Point &b)const{        //点积
 75         return x*b.x+y*b.y;
 76     }
 77     Point operator +(const Point &b)const{
 78         return Point(x+b.x,y+b.y);
 79     }
 80     Point operator -(const Point &b)const{
 81         return Point(x-b.x,y-b.y);
 82     }
 83     Point operator *(double a){
 84         return Point(x*a,y*a);
 85     }
 86     Point operator /(double a){
 87         return Point(x/a,y/a);
 88     }
 89     double len2(){    //长度平方
 90         return sqr(x)+sqr(y);
 91     }
 92     double len(){   //长度
 93         return sqrt(len2());
 94     }
 95     double polar(){    //向量的极角
 96         return atan2(y,x);     //返回与x轴正向夹角(-pi~pi]
 97     }
 98     Point change_len(double r){    //转化为长度为r的向量
 99         double l=len();
100         if(dcmp(l)==0)    return *this;  //零向量
101         return Point(x*r/l,y*r/l);
102     }
103     Point rotate_left(){    //逆时针旋转90度
104         return Point(-y,x);
105     }
106     Point rotate_right(){    //顺时针旋转90度
107         return Point(y,-x);
108     }
109     Point rotate(Point p,double ang){    //绕点p逆时针旋转ang度
110         Point v=(*this)-p;
111         double c=cos(ang),s=sin(ang);
112         return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
113     }
114     Point normal(){        //单位化,逆时针旋转90°
115         return Point(-y/len(),x/len());
116     }
117 };
118 
119 inline double cross(Point a,Point b){    //叉积
120     return a.x*b.y-a.y*b.x;
121 }
122 
123 inline double dis(Point a,Point b){    //两点的距离
124     Point p=b-a;    return p.len();
125 }
126 
127 struct Line{
128     Point s,e;
129     Line(){}
130     Line(Point _s,Point _e):s(_s),e(_e){} //两点确定直线
131     double length(){    //线段长度
132         return dis(s,e);
133     }
134 };
135 
136 double point_to_line(Point p,Line a){    //点到直线距离
137     return fabs(cross(p-a.s,a.e-a.s)/a.length());
138 }
139 
140 struct Circle{
141     Point p;
142     double r;
143     Circle(){}
144     Circle(Point _p,double _r):p(_p),r(_r){}
145 };
146 
147 int relation(Line a,Circle b){    //直线和圆的位置关系  0:相离   1:相切   2:相交
148     double p=point_to_line(b.p,a);
149     if(dcmp(p-b.r)==0)    return 1;
150     return (dcmp(p-b.r)<0? 2: 0);
151 }
152 
153 Point tmp[410];
154 int convex_hull(Point *p,int n,Point *ch){    //求凸包
155     int m=0;
156     sort(p,p+n);
157     for(int i=0;i<n;i++){
158         while(m>1&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<=0)    m--;
159         tmp[m++]=p[i];
160     }
161     int k=m;
162     for(int i=n-2;i>=0;i--){
163         while(m>k&&dcmp(cross(tmp[m-1]-tmp[m-2],p[i]-tmp[m-1]))<=0)    m--;
164         tmp[m++]=p[i];
165     }
166     if(n>1)    m--;
167     for(int i=0;i<m;i++)    ch[i]=tmp[i];
168     return m;
169 }
170 
171 int dp[410][410];
172 Point point[410];
173 Circle circle[120];
174 bool rel[410][410];
175 
176 int main(void){
177     int T;  scanf("%d",&T);
178     while(T--){
179         memset(dp,0,sizeof(dp));
180         memset(rel,0,sizeof(rel));
181         int n,m,ans=0;    double r;   scanf("%d%d%lf",&n,&m,&r);
182         for(int i=0;i<n;i++)    point[i].input();
183         for(int i=0;i<m;i++)    circle[i].p.input(),circle[i].r=r;
184         n=convex_hull(point,n,point);
185         for(int i=0;i<n;i++)
186             for(int j=i+2;j<n-(i==0);j++){
187                 int flag=1;
188                 for(int z=0;z<m;z++)
189                     if(relation(Line(point[i],point[j]),circle[z])){
190                         flag=0;
191                         break;
192                     }
193                 if(flag)    rel[i][j]=rel[j][i]=1;
194             }
195         for(int t=0;t<2*n;t++)
196             for(int s=max(0,t-n+1);s<=t;s++)
197                 for(int i=t;i>=s;i--)
198                     dp[s][t]=max(dp[s][t],dp[s][i]+rel[s%n][t%n]);
199         for(int i=n-1;i<2*n;i++)    ans=max(ans,dp[i-n+1][i]);
200         printf("%d\n",ans);
201     }
202     return 0;
203 }
posted @ 2019-07-29 20:40  DD_BOND  阅读(378)  评论(0编辑  收藏  举报