[计蒜客 商汤科技的行人检测(困难)]概率+几何
来源:互联网 发布:mysql substr 编辑:程序博客网 时间:2024/04/28 00:47
[计蒜客 商汤科技的行人检测(困难)]概率+几何
分类: Math
probability
1. 题目链接
[计蒜客 商汤科技的行人检测(困难)]
2. 题意描述
商汤科技近日推出的 SenseVideo 能够对视频监控中的对象进行识别与分析,包括行人检测等。在行人检测问题中,最重要的就是对行人移动的检测。由于往往是在视频监控数据中检测行人,我们将图像上的行人抽象为二维平面上若干个的点。那么,行人的移动就相当于二维平面上的变换。
在这道题中,我们将行人的移动过程抽象为 旋转、伸缩、平移,有 4 个 移动参数:
。每次行人的移动过程会将行人对应的 nn 个点全部依次应用旋转、伸缩、平移,对于平移前的点 (x, y)(x,y),进行每种操作后的坐标如下:
旋转后的坐标为:
伸缩后的坐标为:
平移后的坐标为:
由于行人移动的特殊性,我们可以确保
很显然,通过变换前后的正确坐标,很容易算出行人的移动参数,但问题没有这么简单。由于行人实际的移动并不会完全按照我们预想的方式进行,因此,会有一部分变换后的坐标结果不正确,但可以确保 结果不正确的坐标数量严格不超过一半。
你现在作为商汤科技的实习生,接手了这个有趣的挑战:算出行人的移动参数。如果不存在一组合法的移动参数,则随意输出一组参数;如果有多种合法的移动参数,输出其中任意一组合法的即可。
输入格式
第一行输入一个整数
接下来
坐标范围在
对于中等版本,
对于困难版本,
输出格式
第一行输出一个浮点数
建议输出保留到
3. 解题思路
中等版本
在中等版本中,除了平移之外,还加入了旋转和拉伸。可以发现只需要枚举哪两对点是正确变换的,就可以计算出对应的拉伸、旋转、平移的量,从而验证是否有严格超过一半的点对满足这组变换。时间复杂度
困难版本
在困难版本中,点对数
注意:
这题精度问题比较严重,尽量不要用
4. 实现代码
#include <set>#include <map>#include <queue>#include <stack>#include <ctime>#include <cmath>#include <cctype>#include <cstdio>#include <string>#include <cstring>#include <cassert>#include <iomanip>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;typedef long double LB;typedef unsigned long long ULL;typedef pair<int, int> PII;typedef pair<LL, LL> PLL;typedef pair<LB, LB> PLB;typedef vector<int> VI;const int INF = 0x3f3f3f3f;const LL INFL = 0x3f3f3f3f3f3f3f3fLL;const long double PI = acos(-1.0);const long double eps = 1e-4;void debug() { cout << endl; }template<typename T, typename ...R> void debug (T f, R ...r) { cout << "[" << f << "]"; debug (r...); }template<typename T> inline void umax(T &a, T b) { a = max(a, b); }template<typename T> inline void umin(T &a, T b) { a = min(a, b); }template <typename T> inline bool scan_d (T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; //EOF while (c != '-' && (c < '0' || c > '9') ) if((c = getchar()) == EOF) return 0; sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1;}template<typename T> void print(T x) { static char s[33], *s1; s1 = s; if (!x) *s1++ = '0'; if (x < 0) putchar('-'), x = -x; while(x) *s1++ = (x % 10 + '0'), x /= 10; while(s1-- != s) putchar(*s1);}template<typename T> void println(T x) { print(x); putchar('\n'); }const int MAXN = 1e5 + 5;int n;struct QNode { LB x[2], y[2]; QNode() {}} cmd[MAXN];int sgn(const LB& a, const LB& b) { if(fabs(b - a) <= eps) return 0; return a < b ? -1 : 1;}PLB f(QNode qd, LB sita, LB scale, LB dx, LB dy) { LB a = (qd.x[0] * cos(sita) - qd.y[0] * sin(sita)) * scale + dx; LB b = (qd.x[0] * sin(sita) + qd.y[0] * cos(sita)) * scale + dy; return make_pair(a, b);}int calc(LB sita, LB scale, LB dx, LB dy) { int cnt = 0; for(int i = 1; i <= n; ++i) { PLB rs = f(cmd[i], sita, scale, dx, dy); if(!sgn(rs.first, cmd[i].x[1]) && !sgn(rs.second, cmd[i].y[1])) ++ cnt; } return cnt;}inline LB dis(LB ax, LB ay, LB bx = 0.0, LB by = 0.0) { LB a = bx - ax; LB b = by - ay; return sqrt(a * a + b * b);}int main() {#ifdef ___LOCAL_WONZY___ freopen ("input.txt", "r", stdin);#endif // ___LOCAL_WONZY___ while(~scanf("%d", &n)) { double x[2], y[2]; for(int i = 1; i <= n; ++i) { scanf("%lf %lf %lf %lf", &x[0], &y[0], &x[1], &y[1]); cmd[i].x[0] = x[0]; cmd[i].x[1] = x[1]; cmd[i].y[0] = y[0]; cmd[i].y[1] = y[1]; } LB sita, scale, dx, dy, delta_x[2], delta_y[2], up, dw; LB ans[4]; if(n == 1) { ans[0] = 0.0; ans[1] = 1.0; ans[2] = cmd[1].x[1] - cmd[1].x[0]; ans[3] = cmd[1].y[1] - cmd[1].y[0]; cout << fixed << setprecision(11) << ans[0] << endl; cout << fixed << setprecision(11) << ans[1] << endl; cout << fixed << setprecision(11) << ans[2] << " " << ans[3] << endl; continue; } int cnt = 0; for(int _ = 100; _--; ) { int i = rand() % n + 1; int j = rand() % n + 1; if(i == j) continue; up = dis(cmd[i].x[1], cmd[i].y[1], cmd[j].x[1], cmd[j].y[1]); dw = dis(cmd[i].x[0], cmd[i].y[0], cmd[j].x[0], cmd[j].y[0]); if(!sgn(dw, 0.0)) continue; scale = up / dw; if(sgn(scale, 10.0) == 1 || sgn(scale, 0) == -1) continue; delta_x[0] = cmd[j].x[0] - cmd[i].x[0]; delta_y[0] = cmd[j].y[0] - cmd[i].y[0]; delta_x[1] = cmd[j].x[1] - cmd[i].x[1]; delta_y[1] = cmd[j].y[1] - cmd[i].y[1]; up = delta_x[0] * delta_x[1] + delta_y[0] * delta_y[1]; dw = dis(delta_x[0], delta_y[0]) * dis(delta_x[1], delta_y[1]); sita = acos(up / dw); dx = cmd[i].x[1] - (cmd[i].x[0] * cos(sita) - cmd[i].y[0] * sin(sita)) * scale; dy = cmd[i].y[1] - (cmd[i].x[0] * sin(sita) + cmd[i].y[0] * cos(sita)) * scale; int ret = calc(sita, scale, dx, dy); if(ret <= cnt) continue; ans[0] = sita; ans[1] = scale; ans[2] = dx; ans[3] = dy; cnt = ret; if(cnt * 2 >= n) break; } cout << fixed << setprecision(11) << ans[0] << endl; cout << fixed << setprecision(11) << ans[1] << endl; cout << fixed << setprecision(11) << ans[2] << " " << ans[3] << endl; }#ifdef ___LOCAL_WONZY___ cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;#endif // ___LOCAL_WONZY___ return 0;}
- [计蒜客 商汤科技的行人检测(困难)]概率+几何
- 计蒜客 商汤科技的行人检测(困难)(计算几何 atan2库函数计算角度)@
- 计蒜客 商汤科技的行人检测(困难)
- 计蒜客 15553 商汤科技的行人检测(困难)
- 计蒜客 2017 第四场 商汤科技的行人检测(中等)(几何)
- 商汤科技的行人检测(简单)
- 计蒜客 第四场 C 商汤科技的行人检测(中等)平面几何好题
- 2017计蒜之道初赛第四场-商汤科技的行人检测(简单)
- 计蒜之道 2017第四场B 商汤科技的行人检测(简单)
- 2017 计蒜之道 第四场 商汤科技的行人检测(简单)
- 2017计蒜之道 第四场 商汤科技的行人检测(简单)
- 2017 计蒜之道 初赛 第四场 (第二题) B. 商汤科技的行人检测(简单)
- 商汤科技的安全令牌
- 行人检测2(行人检测的发展历史)
- CVPR 2016|商汤科技论文解析:人脸检测中级联卷积神经网络的联合训练
- 行人检测(上)-行人检测介绍
- 行人再识别(行人重识别)[包含与行人检测的对比](作者:liuqinglong110)
- 行人再识别(行人重识别)【包含与行人检测的对比】
- Centos 7 安装 Redis
- 双向循环链表实践
- Android卫星菜单
- Android 照片墙功能实现
- centos 7服务器环境搭建
- [计蒜客 商汤科技的行人检测(困难)]概率+几何
- 小人地铁猥亵殴打女乘客 网友发现打人者疑似经济学家
- (bzoj 1003 物流运输)<最短路+DP>
- nginx+memcached 构建页面缓存应用
- programming languages
- 网络 socket 编程 端口 大全
- CodeForces 652C Foe Pairs(思维)
- 关于django model_set 的惨痛教训
- IMWeb提升营Day6 | 训练题32:把数组排成最小的数