[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 }

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

原文地址:https://www.cnblogs.com/137shoebills/p/11267278.html

时间: 2024-10-12 23:38:42

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

HDU 5928 DP 凸包graham

给出点集,和不大于L长的绳子,问能包裹住的最多点数. 考虑每个点都作为左下角的起点跑一遍极角序求凸包,求的过程中用DP记录当前以j为当前末端为结束的的最小长度,其中一维作为背包的是凸包内侧点的数量.也就是 dp[j][k]代表当前链末端为j,其内部点包括边界数量为k的最小长度.这样最后得到的一定是最优的凸包. 然后就是要注意要dp[j][k]的值不能超过L,每跑一次凸包,求个最大的点数量就好了. 和DP结合的计算几何题,主要考虑DP怎么搞 /** @Date : 2017-09-27 17:27

2020-3-14 acm训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019 解题报告+补题报告

2020-3-15比赛解题报告+2020-3-8—2020-3-15的补题报告 2020-3-15比赛题解 训练联盟周赛Preliminaries for Benelux Algorithm Programming Contest 2019  A建筑(模拟) 耗时:3ms 244KB 建筑 你哥哥在最近的建筑问题突破大会上获得了一个奖项 并获得了千载难逢的重新设计城市中心的机会 他最喜欢的城市奈梅根.由于城市布局中最引人注目的部分是天际线, 你的兄弟已经开始为他想要北方和东方的天际线画一些想法

Android 4.4 KitKat升级率已经接近18%(2014-07-09 07:29)

腾讯数码讯(编 译:张秀梅)按照惯例, 每个月的第一个星期的星期一谷歌都会发布最新一期Android版本分布图.从去年十月末谷歌发布Android 4.4 KitKat以来,截止到目前为止Android 4.4 KitKat的升级率以及占到了所有Android设备的18%份额,增长势头非常凶猛. 在 最新一个月的Android版本分布图中一个显著的特征就是除了Android 4.4 KitKat在保持快速持续得增长外,其他的Android在占有率上都有不同程度的下降.Android 4.4 Ki

Python基础教程—2019/1/29

2019/1/29 // 整除** 乘方0x 十六进制 0b 二进制 0o八进制 常用模块和函数1:pow() 乘方 >> pow(2,3)8>> 2**38>> 2:abs() 绝对值 3:round() 向最接近的那个数取整,如果一样,向偶数取整 >> round(2/3)1>>4:math库的floor()函数,向下取整>> import math>> math.floor(32.9)32>> 5:mat

[AtCoder] NIKKEI Programming Contest 2019 (暂缺F)

[AtCoder] NIKKEI Programming Contest 2019 ??本来看见这一场的排名的画风比较正常就来补一下题,但是完全没有发现后两题的AC人数远少于我补的上一份AtCoder. A - Subscribers ??首先始终 \(max = \min(A, B)\) ,\(min\) 的话如果 \(A + B \leq N\) ,那么就是 \(0\) ,否则就是 \(A + B - N\) . int n, a, b; int main() { read(n), read

【AtCoder】Tenka1 Programmer Contest 2019

Tenka1 Programmer Contest 2019 C - Stones 题面大意:有一个01序列,改变一个位置上的值花费1,问变成没有0在1右边的序列花费最少多少 直接枚举前i个都变成0即可 #include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space

Helvetic Coding Contest 2019 差A3 C3 D2 X1 X2

Helvetic Coding Contest 2019 A2 题意:给一个长度为 n 的01序列 y.认为 k 合法当且仅当存在一个长度为 n 的01序列 x,使得 x 异或 x 循环右移 k 位的 01 串得到 y .问合法的 k 的个数. \(n \le 2*10^5\) key:找规律 考虑如何check一个 k 是否合法.那么对于所有的 i 和 i-k 在模 n 的意义下,如果 y 的第 i 位为 0 则二者必须不同,否则必须相同.这样可以用并查集判断是否合法.实际上是把相同的缩起来后

2019.08.29学习整理

2019.08.29学习整理 绑定方法与非绑定方法 绑定方法 对象绑定方法 类的绑定方法 绑定方法:特殊之处,绑定给谁就是谁来调,并且会把自身调过来 类的绑定方法 绑定给类,类来调用,会把类自身传过来 类的绑定方法用在什么地方 不需要通过对象,只需要通过类就能获取到一些东西的时候,用类的绑定方法 类的绑定方法,可以由对象来调 class Person: ''' 注释的内容 ''' def __init__(self,name,age): # print(self) self.name=name

[ICPC训练联盟周赛1] CTU Open Contest 2019

昨天ICPC训练联盟进行了第一场比赛,题目是CTU Open Contest 2019,烟台大学给出了解析. 题目和题解在此(提取码zre3) 我和索队还有yz组队,喊着队友nb就AK了,抱大腿真爽. A题是简单的组合数学,显然有公式 \(1\times C_n^1+2\times C_n^2+ \dots + n \times C_n^n=n \times 2^{n-1}\) 但忘了考虑\(n=0\)的情况,我wa了一发. B题题目我不太读得懂,yz A的. C题是算圆和矩形相交的面积,我抄了