棋盘问题 NOIP1997


【题目描述】

设有一个N×M方格的棋盘(1≤N≤100,1≤M≤100)(1≤N≤100,1≤M≤100)

求出该棋盘中包含有多少个正方形、多少个长方形(不包括正方形)。

例如:当 N=2, M=3时: 

正方形的个数有8个:即边长为1的正方形有6个;

边长为2的正方形有2个。

长方形的个数有10个:

2×1的长方形有4个 :

1×2的长方形有3个:

 

3×1的长方形有2个: 

3×2的长方形有1个: 

【输入】

棋盘的行n和列m.

【输出】

两个整数正方形的个数与长方形的个数.

【样例输入】

2 3

【样例输出】

8 10

解题思路1

看到n和m都是小于100,可以想到遍历的方法,但是具体怎么遍历,还是要好好考虑。

因为知道两个点就可以确定一个矩形,那就从这里入手,利用两个点的行和列循环,一共四层循环,是不会时间超限的。

代码如下:

#include<stdio.h>
int main()
{
	int i,j,a,b;//遍历 
	int n,m;//棋盘的长和宽 
	int sum1=0,sum2=0;//存放正方形和长方形个数 
	scanf("%d %d",&n,&m);
	//以下循环结束条件是:行+1 (n+1)  或  列+1 (m+1)
	//
	for(i=0;i<n+1;i++)//遍历行,代表矩形的左上端点的行 
	{
		for(j=0;j<m+1;j++)//遍历列,代表矩形的左上端点的列 
		{
			for(a=i+1;a<n+1;a++)//代表矩形的右下端点的行 
			//此处 a 要从i+1处开始遍历,防止后面相减出现负数造成重复计算 
			{
				for(b=j+1;b<m+1;b++)//代表矩形右下端点的列
				//也要从j+1处开始遍历 
				{
					if(a-i==b-j)
					sum1++;
					else
					sum2++;
				}
			}
		}
	}
	printf("%d %d\n",sum1,sum2);
	return 0;
} 

如果这个题的n和m的范围更大呢,要选择更快的方法来解决。

解题思路2

好像自己推这个公式还是有点困难,看了别人的解析。

首先算正方形:

边长为1的正方形有:n*m;

边长为2的正方形有:(n-1)*(m-1);

边长为3的正方形有:(n-2)*(m-2);

……

边长为min(n,m)的正方形:(n-min(n,m)+1)*(m-min(n,m)+1);

正方形个数就是边长从1至min(n,m)的正方形之和;

对于矩形(长方形个数就是用矩形个数减去正方形个数):

长为1的矩形有n个;

长为2的矩形有n-1个;

长为3的矩形有n-2个;

……

长为m的矩形有1个;

上述之和为(1+n)/2.

宽为1的矩形有m个;

宽为2的矩形有m-1个;

宽为3的矩形有m-2个;

……

宽为m的矩形有1个;

上述之和为(1+m)/2.

矩形个数就是长从1至n的矩形个数加上宽从1至m的矩形个数。

长方形个数为(1+m)*(n/2)*(1+n)*(m/2)

代码如下:

#include<stdio.h>
int main()
{
	int n,m,i;
	int sum1=0,sum2=0; 
	scanf("%d %d",&n,&m);
	int a=m,b=n;//因为计算正方形数要自减,所以把 n和 m存入另外的变量 
    for(;a>0&&b>0;a--,b--)
	{
		sum1=sum1+a*b;//计算正方形个数 
	}	
	sum2=(1+m)*m*(1+n)*n/4-sum1;//计算长方形个数 
	printf("%d %d",sum1,sum2);
	return 0;
} 

总结

第二种方法明显代码简单很多,有时候题解不止一个两个,当你只想出一种方法,或许会有更多好的方法,要多思考,多练习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值