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 }