[hdu contest 2019-07-29] Azshara's deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法

Posted 鲸头鹳

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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 }
View Code

 

以上是关于[hdu contest 2019-07-29] Azshara's deep sea 计算几何 动态规划 区间dp 凸包 graham扫描法的主要内容,如果未能解决你的问题,请参考以下文章

HDU校赛 | 2019 Multi-University Training Contest 3

2018 Multi-University Training Contest 1 1002 /hdu6299 贪心 1007 /hdu6304 找规律

HDU-5188zhx and contest(贪心+背包)

HDU 5988 Coding Contest(费用流+浮点数)

HDU6804:Contest of Rope Pulling——题解

Coding Contest HDU - 5988