1035 - Tree-Lined Streets

城市绿化树种植算法
本文介绍了一种用于计算城市街道上最多能种植多少树木的算法。该算法考虑了树之间的最小距离限制及树木与交叉口的距离限制,确保交通视线不受阻挡。通过输入街道地图的数据,算法能够计算出在这些限制条件下可以种植的最大树木数量。

The city council of Greenville recently voted to improve the appearance of inner city streets. To provide more greenery in the scenery, the city council has decided to plant trees along all major streets and avenues. To get an idea of how expensive this urban improvement project will be, the city council wants to determine how many trees will be planted. The planting of trees is limited in two ways:

  • Along a street, trees have to be planted at least 50 meters apart. This is to provide adequate grow ing space, and to keep the cost of the project within reasonable limits.
  • Due to safety concerns, no tree should be planted closer than 25 meters along a street to the nearest int ersection. This is to ensure that traffic participants can easily see each other approaching an intersection. Traffic safety should not be compromised by reducing visibility.

All streets considered in this project are straight . They have no turns or bends.

The city council needs to know the maximum number of trees that can be planted under these two restrictions.

Input 

The input consists of descriptions of several street maps. The first line of each description contains an integer  n  (   1$ \le$n$ \le$100 ), which is the number of streets in the map. Each of the following  n  lines describes a street as a line segment in the Cartesian plane. An input line describing a street contains four integers x1 y1 x2 , and  y2 . This means that this street goes from point  (x1y1)  to point  (x2y2) . The coordinates x1 y1 x2 , and  y2  are given in meters, (   0$ \le$x1, y1, x2, y2$ \le$100000 ). Every street has a positive length. Each end point lies on exactly one street.

For each street, the distances between neighboring intersections and/or the end points of the street are not exact multiples of 25 meters. More precisely, the difference of such a distance to the nearest multiple of 25 meters will be at least 0.001 meters. At each intersection, exactly two streets meet.

Input for the last street map description is followed by a line consisting of the number 0.

Output 

For each street map described in the input, first print its number in the sequence. Then print the maximum number of trees that can be planted under the restrictions specified above. Follow the format in the sample output given below.

Sample Input 

3
0 40 200 40
40 0 40 200
0 200 200 0
4
0 30 230 30
0 200 230 200
30 0 30 230
200 0 200 230
3
0 1 121 1
0 0 121 4
0 4 121 0
0

Sample Output 

Map 1
Trees = 13
Map 2
Trees = 20
Map 3
Trees = 7



#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct line
{
	int x1,y1,x2,y2;
};
int cases,n,ans,s,i,j,k;
line a[110];
double b[200];
double len;

bool init()
{
	int i;
	scanf("%d",&n);
	if(n==0)
		return false;
	for(i=1;i<=n;i++)
		scanf("%d %d %d %d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
	return true;
}

double dis(double x,double y)
{
	return sqrt(x*x+y*y);
}

bool check(int x1,int y1,int x2,int y2,int x3,int y3)
{
	long long t1,t2;
	t1=(long long)x1*(long long)y2-(long long)x2*(long long)y1;
	t2=(long long)x1*(long long)y3-(long long)x3*(long long)y1;
	return ((t1>=0&&t2<=0)||(t1<=0&&t2>=0));
}

void cross(line A,line B)
{
	double A1,B1,C1,A2,B2,C2,x,y;
	A1=A.y2-A.y1;B1=A.x1-A.x2;C1=-(A.x1*A1 + A.y1*B1);
	A2=B.y2-B.y1;B2=B.x1-B.x2;C2=-(B.x1*A2 + B.y1*B2);
	x=-(C1*B2-C2*B1)/(A1*B2-A2*B1);
	y=-(A1*C2-A2*C1)/(A1*B2-A2*B1);
	b[s]=dis(x-a[i].x1,y-a[i].y1);
}

int main()
{
	cases=0;
	while(init())
	{
		ans=0;
		for(i=1;i<=n;i++)
		{
			s=2;
			b[1]=-25;
			b[2]=dis(a[i].x2-a[i].x1,a[i].y2-a[i].y1)+25;
			for(j=1;j<=n;j++)
				if(i!=j)
				if(check(a[i].x2-a[i].x1,a[i].y2-a[i].y1, a[j].x1-a[i].x1,a[j].y1-a[i].y1, a[j].x2-a[i].x1,a[j].y2-a[i].y1))
				if(check(a[j].x2-a[j].x1,a[j].y2-a[j].y1, a[i].x1-a[j].x1,a[i].y1-a[j].y1, a[i].x2-a[j].x1,a[i].y2-a[j].y1))
				{
					s++;cross(a[i],a[j]);
				}
				sort(b+1,b+s+1);
				for(j=1;j<s;j++)
				{
					len=b[j+1]-b[j];
					k=(int)(len/50);
					while(len-k*50>1e-6) k++;
					while(len-k*50<1e-6) k--;
					ans+=k;
				}
		}
		printf("Map %d\nTrees = %d\n",++cases,ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不仅仅是寻找

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值