[hdu contest 2019-07-29] Azshara's deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法
今天hdu的比赛的第一题,凸包+区间dp。
给出n个点m个圆,n<400,m<100,要求找出凸包然后给凸包上的点连线,连线的两个点不能(在凸包上)相邻,连线不能与圆相交或相切,连线不能相交但是可以有公共端点。
首先找出凸包,然后把n*n条边和m个圆算点到直线距离验证一下边是否与圆相交存到e[n][n]里。
然后显然是一个dp,但是我开始看错题目了以为不能有公共端点,能有公共端点的情况考虑一下像一个找三角形的过程,就是区间dp。
区间dp有一点妙的地方是最大区间范围是凸包点数而不用+1,因为连线的两个点不能在凸包上相邻所以这样就能直接得到最大值。
今天疯狂坑队友了,我要是帮着队友查错就能多对一道题了,因为自己菜没有写出来题还连累队友真的真的很抱歉。
代码在下面,也算是复习dp和码一个找凸包板子,这个方法好像叫graham扫描法?
1 #include<iostream> 2 #include<cmath> 3 #include<cstdio> 4 #include<cstring> 5 #include<cstdlib> 6 #include<string> 7 #include<algorithm> 8 #include<vector> 9 #include<iomanip> 10 #include<stack> 11 #include<queue> 12 using namespace std; 13 const int maxn=410; 14 int n,m,cnt; 15 int tot; 16 double r; 17 struct nod{ 18 double x,y; 19 }poi[maxn],po[maxn*2],ci[maxn]; 20 bool e[maxn][maxn]={}; 21 int f[maxn*2][maxn*2]={}; 22 bool cmp(nod a,nod b){ 23 double aa=atan2(a.y-po[1].y,a.x-po[1].x); 24 double bb=atan2(b.y-po[1].y,b.x-po[1].x); 25 if(aa==bb) return a.x<b.x; 26 return aa<bb; 27 } 28 double cro(nod a,nod b,nod c){ 29 return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); 30 } 31 void getpo(){ 32 int t=1; 33 for( int i=2; i<=n; ++i) { 34 if( poi[i].y < poi[t].y||( poi[i].y == poi[t].y&&poi[i].x < poi[t].x) ) t=i; 35 } 36 po[++cnt]=poi[t];swap(poi[t],poi[1]); 37 sort(poi+2,poi+n+1,cmp); 38 po[++cnt]=poi[2]; 39 for(int i=3;i<=n;++i){ 40 //cout<<poi[i].x<<poi[i].y<<endl; 41 while(cnt>1&&cro(po[cnt-1],poi[i],po[cnt])>=0)--cnt; 42 po[++cnt]=poi[i]; 43 } 44 } 45 int main(){ 46 int T;scanf("%d",&T); 47 while(T--){ 48 tot=1; 49 cnt=0; 50 memset(e,0,sizeof(e)); 51 memset(f,0,sizeof(f)); 52 scanf("%d%d%lf",&n,&m,&r); 53 for( int i=1; i<=n; ++i) scanf("%lf%lf",&poi[i].x,&poi[i].y); 54 for( int i=1; i<=m; ++i) scanf("%lf%lf",&ci[i].x,&ci[i].y); 55 getpo();//cout<<1111111<<endl; 56 for(int i=1;i<=cnt;++i){ 57 // cout<<po[i].x<<po[i].y<<endl; 58 for(int j=i+2;j<=cnt;++j){ 59 if(i==1&&j==cnt)continue; 60 double a=po[i].y-po[j].y,b=po[j].x-po[i].x; 61 double c=-(a*po[i].x+b*po[i].y); 62 e[i][j]=1; 63 e[j][i]=1; 64 for(int w=1;w<=m;++w){ 65 double ju=a*ci[w].x+b*ci[w].y+c; 66 if(ju<0)ju=-ju; 67 ju/=sqrt(a*a+b*b); 68 if(ju>r)continue; 69 e[i][j]=0; 70 e[j][i]=0; 71 } 72 //cout<<i<<j<<e[i][j]<<endl; 73 } 74 } 75 int ans=0; 76 for(int k=1;k<=cnt;++k){ 77 for(int i=1,j=k;j<cnt*2;++i,++j){ 78 for(int t=i;t<=j;++t){ 79 f[i][j]=max(f[i][j],f[i][t]); 80 if(e[(t-1)%cnt+1][(j-1)%cnt+1])f[i][j]=max(f[i][j],f[i][t]+1); 81 } 82 } 83 } 84 for(int i=1;i<=cnt;++i)ans=max(ans,f[i][i+cnt-1]); 85 printf("%d\n",ans); 86 } 87 return 0; 88 }