FZU 2110 Star
计算几何
训练的题目,给出n个点的坐标(整数),选3个点组成三角形问能形成多少个锐角三角形
直接暴力解决,用三个for循环枚举3个点(升序枚举避免重复),然后用余弦判断三角形中三个角是否为锐角
判断一个角为锐角:已知j,i,k三个点形成一个角,以i为交点向j,k做两个向量a,b,用余弦定理
cos = a*b/( |a| * |b| ) ,因为|a|*|b|必为正整数而且我们不是要算确切的角度只是判断锐,直,钝角所以直接用 a*b
a*b=0 , 直角
a*b>0 , 锐角或0度
a*b<0,钝角或180度
所以不用单纯靠 a*b 的正负来判断是什么叫,对于a*b>0的情况还要判断是否为0度
最后整个数据都是整型,操作也用整型不需要用浮点型,避免精度问题
#include <cstdio> #include <cstring> #include <utility> using namespace std; #define N 110 typedef long long ll; typedef pair<ll , ll> pll; pll p[N]; int n; ll judge(pll a , pll b) { ll c = a.first*b.first + a.second*b.second ; if(c<=0 || (c>0 && a.first*b.second == a.second*b.first)) return -1; return 1; } void solve() { ll count = 0; for(int i=0; i<n; i++) for(int j=i+1; j<n; j++) for(int k=j+1; k<n; k++) { ll f[3]; pll a,b; a.first=p[j].first-p[i].first; a.second=p[j].second-p[i].second; b.first=p[k].first-p[i].first; b.second=p[k].second-p[i].second; f[0]=judge(a,b); a.first=p[i].first-p[j].first; a.second=p[i].second-p[j].second; b.first=p[k].first-p[j].first; b.second=p[k].second-p[j].second; f[1]=judge(a,b); a.first=p[i].first-p[k].first; a.second=p[i].second-p[k].second; b.first=p[j].first-p[k].first; b.second=p[j].second-p[k].second; f[2]=judge(a,b); ll ok=1; for(int i=0; i<3; i++) if(f[i]<0) { ok=0; break;} count += ok; } printf("%I64d\n",count); } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=0; i<n; i++) scanf("%I64d%I64d",&p[i].first , &p[i].second); solve(); } return 0; }