【题目描述】
设有一个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;
}
总结
第二种方法明显代码简单很多,有时候题解不止一个两个,当你只想出一种方法,或许会有更多好的方法,要多思考,多练习。