BZOJ1800 飞行棋

 

给出圆周上的若干个点,已知点与点之间的弧长,其值均为正整数,并依圆周顺序排列。 请找出这些点中有没有可以围成矩形的,并希望在最短时间内找出所有不重复矩形。

Input

第一行为正整数N,表示点的个数,接下来N行分别为这N个点所分割的各个圆弧长度

Output

所构成不重复矩形的个数

Sample Input

8 1 2 2 3 1 1 3 3

Sample Output

3        

                                                                                                         

方法一:      

       这个图形是个圆,要在圆上找矩形。

  重点是矩形的对角线相等。

  然后矩形是内接与这个圆的,所以我们又可以想到,圆的内接矩形对角线等于圆的直径。

  直径,圆的任何一条直径将圆的面积分成相等的两半,直径所在的端点也将周长分成相等的两半。

  如果把弧长相加,能等于周长一半,说明找到一条直径,然后暴力搜索一遍找到所有直径,即所有的对角线。

      为了不与第一组重复,i从1到n-1!!!即可

  每两条对角线都可以形成一个合法矩形,那么只要找出对角线数和矩形个数之间的关系就可以了。

  设有ans条对角线,每一条对角线都可以和剩下的ans-1条配对形成矩形,但是如果全部配对了会有重复,每个矩形都只是重复一次,除以2,所以公式就是   tot=(ans*ans)/2

#include<cstdio>
#include<string>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
	int n,sum=0,ans=0,t=0,j=1;
	scanf("%d",&n);
	int a[n+5];
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	if(sum%2==1)
	{
		printf("0\n");return 0;
	}
	else
	{
		sum/=2;
		for(int i=1;i<n;i++)
		{
			ans+=a[i];
			while(ans>sum)
			{
				ans-=a[j++];
			}
			if(ans==sum)    t++;
		}
		printf("%d\n",t*(t-1)/2);
	}
	return 0;
} 

方法二:

直接暴力,数据量不大,好好看题,要读全。直接遍历四段弧线,两两相等即可以。

n很小,直接枚举四个点即可,注意可以用环来处理,一圈走下来,最后答案除以4,因为每一组会被重复计算4遍(四个点分别做一次起点)

#include<cstdio>
#include<cstring>
int f[45],a[45];
int n,ans;
using namespace std;
int main(){
	scanf("%d",&n);
	f[0]=0;
	for (int i=1;i<=n;i++) scanf("%d",&a[i]),a[i+n]=a[i];
	for (int i=1;i<=n*2;i++)f[i]=f[i-1]+a[i];
	ans=0;
	for (int i=1;i<=n;i++)
		for (int j=i+1;j<=i+n-1;j++)
			for (int k=j+1;k<=i+n-1;k++)
				for (int t=k+1;t<=i+n-1;t++)
					if ((f[t]-f[k]==f[j]-f[i])&&(f[k]-f[j]==f[i+n-1]-f[t]+f[i]-f[i-1])) ans++;
	ans/=4;
	printf("%d",ans);
	return 0;	
} 

猜你喜欢

转载自blog.csdn.net/haohaoxuexilmy/article/details/81841131