【HDU5928 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 G】【计算几何 凸包思想 枚举底点做DP】Birthday Gift 给定绳长最多围住多少个点
2016-10-08 16:41
483 查看
Birthday Gift
Time Limit: 9000/4500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 118 Accepted Submission(s): 24
[align=left]Problem Description[/align]
Both Mr. Frog and Wallice love running. Wallice missed Mr. Frog’s birthday recently,so he decided to give a belated birthday gift. He quickly found out an idea: he decided to run a closed curve to contain those meaningful
buildings. Unfortunately, he only gets a little time left since he is going to attend an important press conference.
Wallice wants to know the maximal number of buildings can be contained in the closed curve. Note that his speed is 1.
[align=left]Input[/align]
The first line contains only one integer T,which indicates the number of test cases.
For each test case, the first line contains an integer N (1≤N≤80),
and a double t (0≤l≤5000)
indicating the numbers of buildings Wallice cares about and the time he has.
In the following n lines, the i-th line contains two doubles xi,yi(−600≤xi,yi≤600)
indicating the position of the buildings.
[align=left]Output[/align]
For each test case,output one line “Case #x: ans’’,where x is the case number (starting from 1) following with ans indicating the maximum number of buildings Wallice can circled in in limited time.
[align=left]Sample Input[/align]
2
4 4.1
0 0
0 1
1 0
1 1
4 3.5
0 0
0 1
1 0
1 1
[align=left]Sample Output[/align]
Case #1: 4
Case #2: 3
Hint
For the second sample, Wallice does not have enough time to circle all the four buildings so he circles three of them instead.
It is guaranteed that the answer would not change even if l changes up to 10^-5, and there would not be any 3 points on one line even if any point changes its position up to 10^-5.
[align=left]Source[/align]
2016CCPC东北地区大学生程序设计竞赛
- 重现赛
#include<stdio.h> #include<iostream> #include<string.h> #include<string> #include<ctype.h> #include<math.h> #include<set> #include<map> #include<vector> #include<queue> #include<bitset> #include<algorithm> #include<time.h> using namespace std; void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } #define MS(x,y) memset(x,y,sizeof(x)) #define ls o<<1 #define rs o<<1|1 typedef long long LL; typedef unsigned long long UL; typedef unsigned int UI; template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; } template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; } const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f; template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; } int casenum, casei; int n; double L; struct P { double x, y; bool operator < (const P b)const { return (x * b.y - y * b.x > 0); //按照斜率从小到大排序 } P operator - (const P b)const { return {x - b.x, y - b.y }; } }p[100], q[100]; double K(double x) { return x*x; } double DIS(P a) { return sqrt(a.x*a.x + a.y*a.y); } double f[100][100]; //f[i][j]表示以st为底端点时,以i为逆时针方向上的最后一个点,恰好包住st~i范围内的j个点的最小绳长 int main() { scanf("%d", &casenum); for (casei = 1; casei <= casenum; ++casei) { scanf("%d%lf", &n, &L); for (int i = 1; i <= n; ++i)scanf("%lf%lf", &p[i].x, &p[i].y); int ans = 1; for (int st = 1; st <= n; ++st) { int g = 0; for (int i = 1; i <= n; ++i) { if (i != st && p[i].y >= p[st].y)q[++g] = p[i] - p[st]; }sort(q + 1, q + g + 1); MS(f, 127); double inf = f[0][0]; for (int i = 1; i <= g; ++i) { f[i][2] = DIS(q[i]); for (int j = i + 1; j <= g; ++j) { double link = DIS(q[j] - q[i]); if (f[i][2] + link > L)continue; int cnt = 1; for (int k = i + 1; k < j; ++k) { //查看k是否能被i-j包住,其实这里应该是 <= ,但是因为不存在三点共线,所以可以用 < if (q[j] - q[i] < q[k] - q[i])++cnt; } //for (int k = 2; f[i][k] != inf; ++k)//另一种写法 for (int k = 2; k <= i + 1 && k + cnt <= j + 1; ++k) { double tmp = f[i][k] + link; if(tmp <= L)gmin(f[j][k + cnt], tmp); } } for (int k = 2; k <= n; ++k)if (f[i][k] + DIS(q[i]) <= L)gmax(ans, k); } } printf("Case #%d: %d\n", casei, ans); } return 0; } /* 【trick&&吐槽】 这里需要注意的是, 1,从最后一个点回到st的距离不能记在f中,因为该距离是可能变小的。 2,不存在三点共线大大简化了问题,否则极角排序在斜率一致的情况下,还要按照距离从近到远做排序 【题意】 有n(80)个点,范围在[-600,600] 有长度为l(0~5000,double类型)的绳子 问你我们用这个绳子最多能围住多少个点(围成凸包围住) 数据保证不会存在三点共线 【类型】 计算几何 【分析】 这是计算几何,不过也在计算几何的基础上加了DP 我们可以枚举最低点st,按照关于st的极角排序(其实就是斜率排序啦,使得所有点都逆时针排列),存在q[]中 然后用f[i][j]表示以st为底端点时,以i为逆时针方向上的最后一个点,恰好包住st~i范围内的j个点的最小绳长 首先f[i][2]=DIS(q[i]) 然后考虑转移 首先枚举转移前的节点i 然后枚举转移后的节点j 然后我们要看i到j的连线可以使得我们包含多少[i+1,j]之间的点,记做cnt 接下来就做转移 gmin(f[j][num + cnt],f[i][num] + DIS(q[i],q[j]) 然后在f[i][k]+dis(q[i])<=L的条件下更新答案就好啦! 【时间复杂度&&优化】 O(n ^ 4) */
相关文章推荐
- hdu 5927 Auxiliary Set 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 F题(树状dp)
- 【HDU5923 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 B】【并查集 暴力 复杂度计算】Prediction 生效若干条链上的所有边条件下的联通块情况
- 【HDU5927 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 F】【dfs序 + 线段树 or 树状数组 复杂度计算】Auxiliary Set 一个点如果是好点或是两个好点的LCA就是好
- HDU Mr. Frog’s Problem 2016CCPC东北地区大学生程序设计竞赛 - 重现赛
- 【HDU5929 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 H】【打表找规律 队列模拟】Basic Data Structure 双端栈下连续1和0做nand的结果
- 【HDU5931 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 J】【线性规划 乱搞】Mission Possible 购买护甲和回复力和速度使得最小成本穿越D距离
- (HDU 5926)Mr. Frog’s Game 水题 <2016CCPC东北地区大学生程序设计竞赛 - 重现赛 >
- (HDU 5927)Auxiliary Set 思维题 <2016CCPC东北地区大学生程序设计竞赛 - 重现赛 >
- HDU Mr. Frog’s Game 2016CCPC东北地区大学生程序设计竞赛 - 重现赛
- HDU Basic Data Structure 2016CCPC东北地区大学生程序设计竞赛 - 重现赛
- 【HDU5922 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 A】【水题】Minimum’s Revenge
- 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 D Coconuts HDU 5925
- (HDU 5929)Basic Data Structure 双端队列+模拟 <2016CCPC东北地区大学生程序设计竞赛 - 重现赛 >
- 【HDU5924 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 C】【水题】Mr. Frog’s Problem
- 【HDU5925 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 D】【离散化 BFS】Coconuts 大地图少数坏点输出每个联通块的大小
- (HDU 5922)Minimum’s Revenge 思维水题 <2016CCPC东北地区大学生程序设计竞赛 - 重现赛 >
- 【HDU5926 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 E】【水题】Mr. Frog’s Game 连连看
- (HDU 5924)Mr. Frog’s Problem 思维水题 <2016CCPC东北地区大学生程序设计竞赛 - 重现赛 >
- 【HDU5930 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 I】【线段树 预处理加变更贡献】GCD 动态修改维护全局gcd数量
- 【HDU5932 2016CCPC东北地区大学生程序设计竞赛 - 重现赛 K】【树上背包 贪心乱搞】Backpack on Tree 物品成本只有12345下的树上背包