算法竞赛入门经典:第五章 基础题目选解 5.12多少块土地

/*
多少块土地:
你有一块椭圆的地。你可以在边界上选n个点,并两两连接得到一个n*(n-1)/2条线段。它们最多能把土地分成多少个部分?
输入:4
输出:8

关键:
注意是求分得多少块面积
欧拉公式:v-e+r = 2,r = 2+e-v - 1(这是椭圆外面的无穷大土地,易漏)=2+n*(n-1)/2-n-1=1+n*(n-3)/2
V=顶点数(线段端点数+交点数)=n+n/4(0~n-2) i*(n-2-i)
E=边数(n段圆弧+线段被切成的段数)=n+n/2(0~n-2) i*(n-2-i)+1
R=面数(土地块数+椭圆外无穷大的面)
假设对角线左边i个顶点,右边n-2-i个顶点,则左右两边两两搭配后在对角线上形成了i*(n-2-i)个交点(因为形成的i*(n-2-i)条边被中间那条线截成了这么多顶点
得到了i*(n-2-i)+1条线段。每个交点被重复计算4次,而每条线段被重复计算2次

土地=E-V+1
E=n段圆弧+切成段=n+n/2(0~n-2) i*(n-2-i)+1
V=端点+交点=n+n/4(0~n-2) i*(n-2-i)
*/
#include <stdio.h>
#include <stdlib.h>

int land(int n)
{
	float V = n;
	float E = n;
	for(int i = 0; i <= n-2;i++)//确保每个顶点从左边有0个顶点到有n-2个顶点,每个顶点为什么重复计算4次?
	{
		V += (n*i*(n-2-i))/4.0;//这里累加必须用浮点数,如果用整数除的话,最后的结果不对
		E += (n*(i*(n-2-i) + 1))/2.0;
	}
	int iLand = E - V + 1;
	printf("%d\n",iLand);
	return iLand;
}

int main(int argc,char* argv[])
{
	int n;
	while(EOF != scanf("%d",&n))
	{
		land(n);
	}
	system("pause");
	return 0;
}












你可能感兴趣的:(算法竞赛)