题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1800
说实话我这几天运气不错,随便在bzoj上找题都可以找到水题,这题在代码上没有丝毫难度,只是如果没想通的话可能做起来会比较吃力,因为暴力也是需要技巧的
方法:
这个图形是个圆,要在圆上找矩形。
然后矩形的特征是啥?四个角90度?好吧这不是重点,重点是矩形的对角线相等。
然后矩形是内接与这个圆的,所以我们又可以想到,圆的内接矩形对角线等于圆的直径。
直径,圆的任何一条直径将圆的面积分成相等的两半,直径所在的端点也将周长分成相等的两半。
只要想通这里,那么思路就来了,如果把弧长相加,能等于周长一半,说明找到一条直径,然后暴力搜索一遍找到所有直径,即所有的对角线。
然后你可以发现,每两条对角线都可以形成一个合法矩形,那么只要找出对角线数和矩形个数之间的关系就可以了。
关系:这个关系还是很好推的,想一想多边形顶点个数和对角线个数怎么找的,类比着找。
设有ans条对角线,每一条对角线都可以和剩下的ans-1条配对形成矩形,但是如果全部配对了会有重复,你随便画个图就可以发现,每个矩形都只是重复一次,
那么就直接除以2就行,所以公式就是 tot=(ans*ans)/2
然后这个主要步骤处理方法比较多,反正都是暴力,我举两个处理的小例子吧
例1:
1 for(int i=1;i<n;i++)//sum是周长的一半 2 { 3 k+=dis[i];//k是累加的长度 4 while(k>sum) 5 { 6 k-=dis[++j]; 7 } 8 if(k==sum) 9 { 10 ans++; 11 } 12 }
例2:
1 for(int i=1;i<=n;i++) 2 //pos是与1配对的对角线另一点,找到这一个点是为了避免对角线重复 3 { 4 tot=0;//tot和例1的k意义相同 5 for(int h=i;h<=n;h++) 6 { 7 tot+=dis[h]; 8 if(tot>=sum) 9 { 10 if(i==1)pos=h; 11 if(tot==sum)ans++; 12 break; 13 } 14 } 15 if(i>=pos)break; 16 }
暴力的方式还有很多,这就简单的介绍两种
然后我们看一看完整的代码
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #define maxn 25 5 using namespace std; 6 7 int sum,ans,dis[maxn],k,j; 8 9 int main() 10 { 11 int n; 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++) 14 { 15 scanf("%d",&dis[i]); 16 sum+=dis[i]; 17 } 18 sum=sum>>1; 19 /* for(int i=1;i<n;i++) 20 { 21 k+=dis[i]; 22 while(k>sum) 23 { 24 k-=dis[++j]; 25 } 26 if(k==sum) 27 { 28 ans++; 29 } 30 }*/ 31 int tot=0,pos=0; 32 for(int i=1;i<=n;i++) 33 { 34 tot=0; 35 for(int h=i;h<=n;h++) 36 { 37 tot+=dis[h]; 38 if(tot>=sum) 39 { 40 if(i==1)pos=h; 41 if(tot==sum)ans++; 42 break; 43 } 44 } 45 if(i>=pos)break; 46 } 47 48 49 cout<<ans*(ans-1)/2; 50 return 0; 51 }