Codeforces 1300D - Aerodynamic
Posted stelayuri
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1300D - Aerodynamic相关的知识,希望对你有一定的参考价值。
题目大意:
***证明给定的图形是中心对称图形
点会按照逆时针顺序给出
x和y都是整数
解题思路:
已经按照逆时针顺序给出,那判断就很容易了
首先,中心对称图形必须是偶数个点,所以n为奇数直接输出NO
然后,输入n个点,根据中心对称图形的性质,又因为点按照逆时针给出,可得
第1个点和第n/2+1个点
第2个点和第n/2+2个点
第3个点和第n/2+3个点
...
第n/2个点和第n个点
这些两点组合它们的线段会同时交于一点,且这个点也是它们线段的中点
根据这个性质,先记录下第1个点和第n/2+1个点组成线段的中点,就能知道这整个图形的中点(cx,cy)
接下来最多只需要再判断n/2-1组点对就能得出判断结果了
为了防止取中点时/2的误差,所以点要用double储存
正常情况下对于double计算精度问题需要用eps判断两点是否相等,但是由于这题给定的点是整数,/2后最坏情况只能拿到个.5的浮点部分,所以二进制储存是精确的,不需要加eps
代码1(717ms):
1 #include<bits/stdc++.h> 2 using namespace std; 3 double x[300050],y[300050]; 4 int main(){ 5 ios::sync_with_stdio(0); 6 cin.tie(0);cout.tie(0); 7 int n,i,j; 8 double cx,cy,dx,dy; 9 cin>>n; 10 if(n&1){ 11 cout<<"NO "; 12 return 0; 13 } 14 for(i=1;i<=n;i++) 15 cin>>x[i]>>y[i]; 16 cx=(x[1]+x[n/2+1])/2.0; 17 cy=(y[1]+y[n/2+1])/2.0; 18 for(i=2,j=n/2+2;j<=n;i++,j++){ 19 dx=(x[i]+x[j])/2.0; 20 dy=(y[i]+y[j])/2.0; 21 if(cx!=dx||cy!=dy){ 22 cout<<"NO "; 23 return 0; 24 } 25 } 26 cout<<"YES "; 27 28 return 0; 29 }
发现这样耗时很大,所以要对计算进行优化
首先可以发现,所有计算中点的式子都有一个/2
如果把所有的/2都去掉,对答案的判断是不会变的
所以double此时也可以改成int了(两种类型计算方式不同时间差别很大)
因为点的最大值只有1e9,相加最大2e9,不会超出int范围,所以不需要开long long
然后,从读入入手,可以先读n/2+1个点,剩下的n/2-1个点边读入边判断(减少这中间的耗时,虽然也差不了多少)
最后,就可以拿到一份看起来更清爽的代码啦
代码2(109ms):
1 #include<bits/stdc++.h> 2 using namespace std; 3 int x[300050],y[300050]; 4 int main(){ 5 ios::sync_with_stdio(0); 6 cin.tie(0);cout.tie(0); 7 int n,i,j,cx2,cy2; 8 cin>>n; 9 if(n&1){ 10 cout<<"NO "; 11 return 0; 12 } 13 for(i=1;i<=n/2;i++) 14 cin>>x[i]>>y[i]; 15 cin>>x[n/2+1]>>y[n/2+1]; 16 cx2=x[1]+x[n/2+1]; 17 cy2=y[1]+y[n/2+1]; 18 for(i=2,j=n/2+2;j<=n;i++,j++){ 19 cin>>x[j]>>y[j]; 20 if(x[i]+x[j]!=cx2||y[i]+y[j]!=cy2){ 21 cout<<"NO "; 22 return 0; 23 } 24 } 25 cout<<"YES "; 26 27 return 0; 28 }
以上是关于Codeforces 1300D - Aerodynamic的主要内容,如果未能解决你的问题,请参考以下文章