1095 - Contour Mapping

A contour map represents the topography of a given region. Lines on a contour map represent constant elevations. For example, a contour map might contain a line that represents points with an elevation of 100 meters above mean sea level, another line representing 200 meters elevation, and so on.


The Association for Contour Mapping (ACM) needs a program to produce contour maps from data files containing elevation measurements collected by a satellite. They are especially interested in the total length of all contour lines on each map. The elevation data is in the form of sequences of integers that represent elevations measured at regular intervals along scan lines that run from west to east. The spacing of the scan lines is such that each elevation measurement in the interior of the data set has six nearest neighbors and is equidistant from them (when elevation is ignored), as shown in Figure 5 and Figure 6.

\epsfbox{p4790.eps}

The policy of the ACM is to approximate the actual terrain by a set of triangles constructed by connecting each elevation measurement to its nearest neighbors by straight line segments. Each of these triangles is then treated as a planar surface, where the plane is determined by the coordinates, including elevation, of the vertices. If the triangles are projected onto the zero-elevation plane, they form a set of equilateral triangles.


In the figures above, the black numbers represent elevation data and the red dashed lines and numbers represent contour lines. Figure 5 contains a single contour line at elevation 5. Figure 6 contains multiple contour lines at elevations 6 and 9. A contour line may pass through the interior of a triangle or run along an edge of a triangle.

Because of the way the data points are interlaced, even-numbered scan lines contain one more data point than odd-numbered scan lines. In each figure, the first scan line is shown at the top.

Input 

The input consists of several test cases, each containing a set of elevation data. Each test case begins with a line containing four integers as follows:


  • s (2$ \le$s$ \le$100) is the number of scan lines of data in the test case.
  • p (1$ \le$p$ \le$100) is the number of elevation measurements on the odd numbered scan lines. The evennumbered scan lines contain p + 1 elevation measurements.
  • d (1$ \le$d$ \le$10) is the distance between each elevation measurement and its nearest neighbors when elevation is ignored (equals the side-length of the equilateral triangles in the figures.)
  • h (1$ \le$h$ \le$1000) is the elevation increment between contour lines in the desired map. The final contour map contains a contour line wherever the elevation is an exact multiple of h. Note that a map may contain multiple contour lines for a given elevation. Where a region is level, contour lines are shown only for the boundaries. (See for example the contour line of elevation 9 in Figure 6.)


The first line of each test case is followed by additional lines containing elevation data as a sequence of nonnegative integers no larger than 106. The first p integers represent the elevation measurements on the first scan line, from left to right. The next p + 1 integers represent the elevation measurements on the second scan line, reading from left to right. The data continues in order, providing p integers for each odd-numbered scan line and p + 1 integers for each even-numbered scan line, until all the elevation data has been provided. Each test case ends with an empty line.

The input is terminated with a line containing a single zero.

Output 

For each test case, display its case number followed by the total length of all the contour lines on the contour map, rounded to the nearest integer. Follow the format of the sample output.

Sample Input 

3 2 5 5 
1 1 
1 9 1 
1 1 

4 4 5 3 
5 7 7 5 
5 9 9 9 5
9 9 9 9 
7 9 9 9 7

0

Sample Output 

Case 1: 15 
Case 2: 54





#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
const int MAXN=110;
const int COSA=0.5;
int s,p,d,h;
int a[MAXN][MAXN];
double ans;
void init()
{
	scanf("%d %d %d",&p,&d,&h);
	int i,j;
	for(i=1;i<=s;++i)
	{
		for(j=1;j<=p+1-(i&1);++j)
			scanf("%d",&a[i][j]);
	}
}

void makeswap(int &a,int &b)
{
	if(a>b)
	{
		int t=a;
		a=b;
		b=t;
	}
}

inline double gettri(double a,double b)
{
	return sqrt(a*a+b*b-2*a*b*COSA);
}

inline double gethalflong(int a,int b,int c,int l,int r)
{
	if(l>r)
		return 0;
	double L=gettri(double(l-a)/double(b-a)*d,double(l-a)/double(c-a)*d);
	double R=gettri(double(r-a)/double(b-a)*d,double(r-a)/double(c-a)*d);
	return (L+R)*((r-l)/h+1)/2;
}

double getlong(int a,int b,int c)
{
	makeswap(a,b);
	makeswap(b,c);
	makeswap(a,b);
	double ret;
	int l,m1,m2,r;
	if(a==c)
	{
		if(a%h==0)
			return d*1.5;
	}
	if(a==b)
	{
		l=(a/h)*h;
		if(l<a)
			l+=h;
		r=(c/h)*h;
		ret=gethalflong(-c,-b,-a,-r,-l);
	}
	else if(b==c)
	{
		l=(a/h)*h+h;
		r=(c/h)*h;
		ret=gethalflong(a,b,c,l,r);
	}
	else
	{
		l=(a/h)*h+h;
		m2=(b/h)*h+h;
		m1=m2-h;
		r=(c/h)*h;
		if(r==c)
			r-=h;
		ret=gethalflong(a,b,c,l,m1)+gethalflong(-c,-b,-a,-r,-m2);
	}
	if((b%h==0)&&((a==b)||(b==c)))
		ret-=d*0.5;
	return ret;
}

bool equal(int a,int b,int c,int d)
{
	return (a==b)&&(b==c)&&(c==d);
}

void solve()
{
	ans=0;
	int i,j;
	for(i=1;i<s;i+=2)
	{
		for(j=1;j<p;++j)
		{
			ans+=getlong(a[i][j],a[i+1][j],a[i+1][j+1]);
			ans+=getlong(a[i][j],a[i][j+1],a[i+1][j+1]);
		}
		ans+=getlong(a[i][p],a[i+1][p],a[i+1][p+1]);
		if((a[i][1]==a[i+1][1])&&(a[i][1]%h==0))
			ans+=d*0.5;
		if((a[i][p]==a[i+1][p+1])&&(a[i][p]%h==0))
			ans+=d*0.5;
	}
	for(i=1;i<s;i+=2)
	{
		for(j=1;j<p;++j)
		{
			ans+=getlong(a[i][j],a[i+1][j],a[i+1][j+1]);
			ans+=getlong(a[i+1][j+1],a[i][j+1],a[i+1][j]);
		}
		ans+=getlong(a[i][p],a[i+1][p],a[i+1][p+1]);
		if((a[i][1]==a[i+1][1])&&(a[i][1]%h==0))
			ans+=d*0.5;
		if((a[i][p+1]==a[i+1][p])&&(a[i][p+1]%h==0))
			ans+=d*0.5;
	}
	for(i=1;i<p;++i)
		if((a[1][i]==a[1][i+1])&&(a[1][i]%h==0))
			ans+=d*0.5;
	for(i=1;i<p+1-(s&1);++i)
		if((a[s][i]==a[s][i+1])&&(a[s][i]%h==0))
			ans+=d*0.5;
	for(i=1;i<s;i+=2)
	{
		for(j=1;j<p;++j)
			if(a[i][j]%h==0)
			{
				if(equal(a[i][j],a[i+1][j],a[i][j+1],a[i+1][j+1]))
					ans-=d;
				if(equal(a[i][j],a[i][j+1],a[i+1][j+1],a[i+1][j+2]))
					ans-=d;
			}
			if(i<s-1)
				for(j=1;j<=p;++j)
					if(a[i][j]%h==0)
						if(equal(a[i][j],a[i+1][j],a[i+2][j],a[i+1][j+1]))
							ans-=d;
	}
	for(i=2;i<s;i+=2)
	{
		for(j=1;j<p;++j)
			if(a[i][j+1]%h==0)
			{
				if(equal(a[i][j],a[i+1][j],a[i][j+1],a[i+1][j+1]))
					ans-=d;
				if(equal(a[i+1][j],a[i][j+1],a[i+1][j+1],a[i][j+2]))
					ans-=d;
			}
			if(i<s-1)
				for(j=1;j<p;++j)
					if(a[i][j+1]%h==0)
						if(equal(a[i][j+1],a[i+1][j+1],a[i+2][j+1],a[i+1][j]))
							ans-=d;
	}
	printf("%.0f\n",ans);
}

int main()
{
	int CASE=0;
	while((scanf("%d",&s)!=EOF)&&s)
	{
		init();
		printf("Case %d: ",++CASE);
		solve();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不仅仅是寻找

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

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

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

打赏作者

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

抵扣说明:

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

余额充值