Day7 T1 直角三角形
时间:2019-09-13
本文章向大家介绍Day7 T1 直角三角形,主要包括Day7 T1 直角三角形使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目
二维平面坐标系中有N个点。从N个点选择3个点,问有多少选法使得这3个点形成直角三角形。
输入
第一行包含一个整数N(3 \(\leqslant\) N \(\leqslant\) 1500),表示点数。
接下来N行,每行包含两个用空格隔开的整数表示每个点的坐标,坐标值在\(-10^9\)到\(10^9\)之间。每个点位置互不相同。
输出
输出直角三角形的数量。
样例
输入 | 输出 |
---|---|
3 4 2 2 1 1 3 |
1 |
4 5 0 2 6 8 6 5 7 |
0 |
5 -1 1 -1 0 0 0 1 0 1 1 |
7 |
题解
固定一个点P,平移整个坐标系,使得P为原点。现在,对于每个点,首先确定其所在的象限,然后将其旋转k•90°(k∈Z),使其落在第一象限中。之后,按照过点的正比例函数的斜率k(纵坐标除以横坐标)对所有点进行排序。如果两个点斜率相同并且旋转之前在相邻的象限中,它们就能形成以P为直角顶点的直角三角形。排序后,对于每一组斜率相同的点,统计它们原来在每个象限的点的个数,并将相邻象限的点的数量相乘。时间复杂度为\(O(N^2logN)\)。(这就是为什么\(O(N^3)\)的暴力枚举在加一堆玄学优化后也能卡过:因为正解的时间复杂度也不低)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n;
int x[1510],y[1510];
ll ans=0;
struct node{
ll x,y;
int qua;
};
node cpy[1510];
bool cmp(node a,node b){
return a.y*b.x<a.x*b.y;
//将不等式变形成两边都是乘法运算,避免除法运算带来的精度损失
}
void rotate(int m){
if(cpy[m].x==0 && cpy[m].y==0) return;//如果是原点,无需旋转
cpy[m].qua=1;
while(cpy[m].x<=0 || cpy[m].y<0){
swap(cpy[m].x,cpy[m].y);
cpy[m].y=-cpy[m].y;
cpy[m].qua++;//如果一个点需要顺时针旋转n次才落在第一象限,那么其原象限为n+1
//最多旋转3次(原来在第四象限),所以这里无需像隔壁熊泽恩同学写的那样取模
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d %d",&x[i],&y[i]);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cpy[j].x=x[j]-x[i];
cpy[j].y=y[j]-y[i];
rotate(j);
}
swap(cpy[1],cpy[i]);//不要把原点给算进去了
sort(cpy+2,cpy+n+1,cmp);
int j=2;
while(j<=n){
int cnt[5]={0};
int k=j;
while(k<=n && cpy[j].y*cpy[k].x==cpy[j].x*cpy[k].y){
cnt[cpy[k].qua]++;
k++;
}
for(int t=1;t<4;t++) ans+=cnt[t]*cnt[t+1];
ans+=cnt[1]*cnt[4];
j=k;
}
}
printf("%lld",ans);
return 0;
}
原文地址:https://www.cnblogs.com/znk161223/p/11516691.html
- OpenDaylight Carbon二次开发实用指南
- 报警系统QuickAlarm之频率统计及接口封装
- 如何使用Sentry管理Hive外部表权限
- 报警系统QuickAlarm之报警规则解析
- 报警系统QuickAlarm之报警规则的设定与加载
- 报警系统QuickAlarm之报警执行器的设计与实现
- 如何在Kerberos与非Kerberos的CDH集群BDR不可用时复制数据
- 一个可扩展的报警系统Quick-Alarm
- 如何借助GitHub搭建属于自己的maven仓库
- Java可以如何实现文件变动的监听
- 如何在CDH中安装Kudu&Spark2&Kafka
- 秒懂 javascript 拖拽上传文件
- 一款轻量级树形控件EasyTreeview
- 大白话谈 Git
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Flutter基础widgets教程-IntrinsicHeight篇
- Flutter基础widgets教程-Baseline篇
- springcloud本地开发的微服务如何调用远程k8s的微服务
- Flutter基础widgets教程-LimitedBox篇
- 算法:滑动窗口(二)
- Flutter基础widgets教程-LinearProgressIndicator篇
- Flutter基础widgets教程-ListTile篇
- 深入剖析 linux GCC 4.4 的 STL String
- Flutter基础widgets教程-MaterialApp篇
- 如何使用Visual Studio Code开发Django项目
- Flutter基础widgets教程-Padding篇
- Flutter基础widgets教程-Placeholder篇
- Flutter基础widgets教程-PopupMenuButton篇
- Python部署rad+xray自动化
- 2.建立第一个django项目与配置