题目
多少正方形?
枚举
设每个横纵相邻点得间距为1,则我们可以依次输出下列边长为 a a a的正方形的数量:
边长为1
a
=
1
a=1
a=1
边长为 2 \sqrt{2} 2
a
=
1
2
+
1
2
=
2
a=\sqrt{1^2+1^2}=\sqrt{2}
a=12+12=2
边长为 5 \sqrt{5} 5
a
=
1
2
+
2
2
=
5
a=\sqrt{1^2+2^2}=\sqrt{5}
a=12+22=5
边长为 8 \sqrt{8} 8
a = 2 2 + 2 2 = 8 a=\sqrt{2^2+2^2}=\sqrt{8} a=22+22=8
边长为 13 \sqrt{13} 13
a
=
2
2
+
3
2
=
13
a=\sqrt{2^2+3^2}=\sqrt{13}
a=22+32=13
按上述尺寸数得各个大小正方形数量如下:
{ C 1 = 9 a = 1 C 2 = 4 a = 1 2 + 1 2 = 2 C 3 = 2 a = 1 2 + 2 2 = 5 C 4 = 4 a = 2 2 + 2 2 = 2 2 C 5 = 2 a = 2 2 + 3 2 = 13 \begin{cases} C_1=9 &\text{ } a=1 \\ C_2=4 &\text{ } a=\sqrt{1^2+1^2}=\sqrt{2}\\ C_3=2 &\text{ } a=\sqrt{1^2+2^2}=\sqrt{5}\\ C_4=4 &\text{ } a=\sqrt{2^2+2^2}=2\sqrt{2}\\ C_5=2 &\text{ } a=\sqrt{2^2+3^2}=\sqrt{13} \end{cases} ⎩ ⎨ ⎧C1=9C2=4C3=2C4=4C5=2 a=1 a=12+12=2 a=12+22=5 a=22+22=22 a=22+32=13
C
=
C
1
+
C
2
+
C
3
+
C
4
+
C
5
=
9
+
4
+
2
+
4
+
2
=
21
\begin{equation} \begin{split} C&=C_1+C_2+C_3+C_4+C_5 \\ &=9+4+2+4+2 \\ &=21 \end{split} \end{equation}
C=C1+C2+C3+C4+C5=9+4+2+4+2=21
扩展-使用代码来数
1、定义点对象
/// <summary>
/// 点对象
/// </summary>
public class CPoint
{
/// <summary>
/// 点横坐标
/// </summary>
public double X { get; set; }
/// <summary>
/// 点纵坐标
/// </summary>
public double Y { get; set; }
/// <summary>
/// 点相对位置角度
/// </summary>
public double Angle { get; set; }
/// <summary>
/// 点编号
/// </summary>
public int Index { get; set; }
public CPoint(int index,double x,double y,double a = 0)
{
this.X = x;
this.Y = y;
this.Index = index;
this.Angle = a;
}
/// <summary>
/// 判断两个点是否是同一个点
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(CPoint)) return false;
var val =(CPoint) obj;
if(this.X == val.X && this.Y == val.Y)
{
return true;
}
return false;
}
/// <summary>
/// 格式化点对象
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"{Index}.({X},{Y}){Angle}";
}
/// <summary>
/// 50倍绘制圆点
/// </summary>
/// <returns></returns>
public RectangleF DrawCircle()
{
float size = 10;
return new RectangleF((float)(X *50 - size / 2), (float)(Y *50 - size / 2), size, size);
}
/// <summary>
/// 50倍绘制点
/// </summary>
/// <returns></returns>
public PointF DrawPnt()
{
return new PointF((float)(X * 50), (float)(Y * 50));
}
}
2、定义正方形对象
/// <summary>
/// 正方形对象
/// </summary>
public class CSqure
{
/// <summary>
/// 正方形的点
/// </summary>
public List<CPoint> Points { get; set; }
/// <summary>
/// 正方形边长
/// </summary>
public double C { get; set; }
/// <summary>
/// 正方形中心点横坐标
/// </summary>
public double CenterX { get; set; }
/// <summary>
/// 正方形中心点纵坐标
/// </summary>
public double CenterY { get; set; }
public CSqure(CPoint pnt1, CPoint pnt2, CPoint pnt3, CPoint pnt4)
{
if (Points == null)
{
Points = new List<CPoint>();
}
Points.Add(pnt1);
Points.Add(pnt2);
Points.Add(pnt3);
Points.Add(pnt4);
}
public PointF[] DrawSqure()
{
return new PointF[4] { Points[0].DrawPnt(), Points[1].DrawPnt(), Points[2].DrawPnt(), Points[3].DrawPnt() };
}
public PointF DrawCenter(SizeF size)
{
var center = CalculateCenter();
var pnt = center.DrawPnt();
return new PointF(pnt.X - size.Width / 2, pnt.Y - size.Height / 2);
}
/// <summary>
/// 判断是否正方形
/// </summary>
/// <returns></returns>
public bool IsSqure()
{
List<double> distances = new List<double>();
// Calculate all pairwise distances
for (int i = 0; i < Points.Count; i++)
{
for (int j = i + 1; j < Points.Count; j++)
{
distances.Add(Distance(Points[i], Points[j]));
}
}
// 将所有点得距离进行排序
distances.Sort();
// 第一个距离必须大于0,前四个距离依次相等是边,后两个距离是对象线。四边相等且对角线相等为正方形
if (distances[0] > 0 && Equal(distances[0], distances[1]) && Equal(distances[1], distances[2]) && Equal(distances[2], distances[3]) &&
Equal(distances[4], distances[5]))
{
C = distances[0];
//计算每个点得顺序
List<CPoint> polygons = new List<CPoint>();
var center = CalculateCenter();
CenterX = center.X;
CenterY = center.Y;
for (int i = 0; i < Points.Count; i++)
{
var angle = CalculateAngle(center, Points[i]);
if (angle < 0)
{
angle += 360;
}
else if (angle >= 360)
{
angle -= 360;
}
polygons.Add(new CPoint(Points[i].Index, Points[i].X, Points[i].Y, angle));
}
Points = polygons.OrderBy(o => o.Angle).ToList();
return true;
}
return false;
}
/// <summary>
/// 计算正方形中心点
/// </summary>
/// <returns></returns>
public CPoint CalculateCenter()
{
double centerX = Points.Average(o => o.X);
double centerY = Points.Average(o => o.Y);
return new CPoint(0, centerX, centerY);
}
/// <summary>
/// 计算旋转角
/// </summary>
/// <param name="center"></param>
/// <param name="point"></param>
/// <returns></returns>
public double CalculateAngle(CPoint center, CPoint point)
{
double deltaY = point.Y - center.Y;
double deltaX = point.X - center.X;
double angleInRadians = Math.Atan2(deltaY, deltaX);
double angleInDegrees = angleInRadians * (180.0 / Math.PI);
return angleInDegrees;
}
/// <summary>
/// 判断两个距离是否相等
/// </summary>
/// <param name="d1"></param>
/// <param name="d2"></param>
/// <returns></returns>
public bool Equal(double d1, double d2)
{
if (Math.Abs(d2 - d1) < 0.000001)
{
return true;
}
return false;
}
/// <summary>
/// 计算两点之间的距离
/// </summary>
/// <param name="pnt1"></param>
/// <param name="pnt2"></param>
/// <returns></returns>
public double Distance(CPoint pnt1, CPoint pnt2)
{
double a = pnt1.X - pnt2.X;
double b = pnt1.Y - pnt2.Y;
double c = Math.Sqrt(a * a + b * b);
return c;
}
/// <summary>
/// 判断两个正方形是否是同一个正方形
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(CSqure)) return false;
var val = (CSqure)obj;
if (this.ToString() == obj.ToString())
{
return true;
}
return false;
}
/// <summary>
/// 格式化正方形对象
/// </summary>
/// <returns></returns>
public override string ToString()
{
var temps = Points.OrderBy(o => o.Index);
return string.Join("-", temps.Select(o => o.Index));
}
/// <summary>
/// 根据点获取所有正方形
/// </summary>
/// <param name="Points"></param>
/// <returns></returns>
public static List<CSqure> GetAllSqures(List<CPoint> Points)
{
List<CSqure> Squres = new List<CSqure>();
for (int i = 0; i < Points.Count(); i++)
{
for (int j = 0; j < Points.Count(); j++)
{
for (int k = 0; k < Points.Count(); k++)
{
for (int l = 0; l < Points.Count(); l++)
{
CSqure squre = new CSqure(Points[i], Points[j], Points[k], Points[l]);
if (squre.IsSqure())//判断是不是正方形
{
bool isExist = false;
foreach (var item in Squres)
{
if (item.ToString() == squre.ToString()) //判断是不是已经存在
{
isExist = true;
break;
}
}
if (!isExist)//没有找到过则添加到列表
{
Squres.Add(squre);
}
}
}
}
}
}
Squres = Squres.OrderBy(o => o.C).ThenBy(o => o.CenterY).ThenBy(o => o.CenterX).ToList();
return Squres;
}
}
3、初始化所有点
//Points.Add(new CPoint(index++, 1, 1, 0));
//Points.Add(new CPoint(index++, 1, 2, 0));
Points.Add(new CPoint(index++, 1, 3, 0));
Points.Add(new CPoint(index++, 1, 4, 0));
//Points.Add(new CPoint(index++, 1, 5, 0));
//Points.Add(new CPoint(index++, 1, 6, 0));
//Points.Add(new CPoint(index++, 2, 1, 0));
//Points.Add(new CPoint(index++, 2, 2, 0));
Points.Add(new CPoint(index++, 2, 3, 0));
Points.Add(new CPoint(index++, 2, 4, 0));
//Points.Add(new CPoint(index++, 2, 5, 0));
//Points.Add(new CPoint(index++, 2, 6, 0));
Points.Add(new CPoint(index++, 3, 1, 0));
Points.Add(new CPoint(index++, 3, 2, 0));
Points.Add(new CPoint(index++, 3, 3, 0));
Points.Add(new CPoint(index++, 3, 4, 0));
Points.Add(new CPoint(index++, 3, 5, 0));
Points.Add(new CPoint(index++, 3, 6, 0));
Points.Add(new CPoint(index++, 4, 1, 0));
Points.Add(new CPoint(index++, 4, 2, 0));
Points.Add(new CPoint(index++, 4, 3, 0));
Points.Add(new CPoint(index++, 4, 4, 0));
Points.Add(new CPoint(index++, 4, 5, 0));
Points.Add(new CPoint(index++, 4, 6, 0));
//Points.Add(new CPoint(index++, 5, 1, 0));
//Points.Add(new CPoint(index++, 5, 2, 0));
Points.Add(new CPoint(index++, 5, 3, 0));
Points.Add(new CPoint(index++, 5, 4, 0));
//Points.Add(new CPoint(index++, 5, 5, 0));
//Points.Add(new CPoint(index++, 5, 6, 0));
//Points.Add(new CPoint(index++, 6, 1, 0));
//Points.Add(new CPoint(index++, 6, 2, 0));
Points.Add(new CPoint(index++, 6, 3, 0));
Points.Add(new CPoint(index++, 6, 4, 0));
//Points.Add(new CPoint(index++, 6, 5, 0));
//Points.Add(new CPoint(index++, 6, 6, 0));
4、调用
public List<CSqure> Squres = CSqure.GetAllSqures(Points);
完整代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
/// <summary>
/// 点对象
/// </summary>
public class CPoint
{
/// <summary>
/// 点横坐标
/// </summary>
public double X { get; set; }
/// <summary>
/// 点纵坐标
/// </summary>
public double Y { get; set; }
/// <summary>
/// 点相对位置角度
/// </summary>
public double Angle { get; set; }
/// <summary>
/// 点编号
/// </summary>
public int Index { get; set; }
public CPoint(int index,double x,double y,double a = 0)
{
this.X = x;
this.Y = y;
this.Index = index;
this.Angle = a;
}
/// <summary>
/// 判断两个点是否是同一个点
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(CPoint)) return false;
var val =(CPoint) obj;
if(this.X == val.X && this.Y == val.Y)
{
return true;
}
return false;
}
/// <summary>
/// 格式化点对象
/// </summary>
/// <returns></returns>
public override string ToString()
{
return $"{Index}.({X},{Y}){Angle}";
}
/// <summary>
/// 50倍绘制圆点
/// </summary>
/// <returns></returns>
public RectangleF DrawCircle()
{
float size = 10;
return new RectangleF((float)(X *50 - size / 2), (float)(Y *50 - size / 2), size, size);
}
/// <summary>
/// 50倍绘制点
/// </summary>
/// <returns></returns>
public PointF DrawPnt()
{
return new PointF((float)(X * 50), (float)(Y * 50));
}
}
/// <summary>
/// 正方形对象
/// </summary>
public class CSqure
{
/// <summary>
/// 正方形的点
/// </summary>
public List<CPoint> Points { get; set; }
/// <summary>
/// 正方形边长
/// </summary>
public double C { get; set; }
/// <summary>
/// 正方形中心点横坐标
/// </summary>
public double CenterX { get; set; }
/// <summary>
/// 正方形中心点纵坐标
/// </summary>
public double CenterY { get; set; }
public CSqure(CPoint pnt1, CPoint pnt2, CPoint pnt3, CPoint pnt4)
{
if (Points == null)
{
Points = new List<CPoint>();
}
Points.Add(pnt1);
Points.Add(pnt2);
Points.Add(pnt3);
Points.Add(pnt4);
}
public PointF[] DrawSqure()
{
return new PointF[4] { Points[0].DrawPnt(), Points[1].DrawPnt(), Points[2].DrawPnt(), Points[3].DrawPnt() };
}
public PointF DrawCenter(SizeF size)
{
var center = CalculateCenter();
var pnt = center.DrawPnt();
return new PointF(pnt.X - size.Width / 2, pnt.Y - size.Height / 2);
}
/// <summary>
/// 判断是否正方形
/// </summary>
/// <returns></returns>
public bool IsSqure()
{
List<double> distances = new List<double>();
// Calculate all pairwise distances
for (int i = 0; i < Points.Count; i++)
{
for (int j = i + 1; j < Points.Count; j++)
{
distances.Add(Distance(Points[i], Points[j]));
}
}
// 将所有点得距离进行排序
distances.Sort();
// 第一个距离必须大于0,前四个距离依次相等是边,后两个距离是对象线。四边相等且对角线相等为正方形
if (distances[0] > 0 && Equal(distances[0], distances[1]) && Equal(distances[1], distances[2]) && Equal(distances[2], distances[3]) &&
Equal(distances[4], distances[5]))
{
C = distances[0];
//计算每个点得顺序
List<CPoint> polygons = new List<CPoint>();
var center = CalculateCenter();
CenterX = center.X;
CenterY = center.Y;
for (int i = 0; i < Points.Count; i++)
{
var angle = CalculateAngle(center, Points[i]);
if (angle < 0)
{
angle += 360;
}
else if (angle >= 360)
{
angle -= 360;
}
polygons.Add(new CPoint(Points[i].Index, Points[i].X, Points[i].Y, angle));
}
Points = polygons.OrderBy(o => o.Angle).ToList();
return true;
}
return false;
}
/// <summary>
/// 计算正方形中心点
/// </summary>
/// <returns></returns>
public CPoint CalculateCenter()
{
double centerX = Points.Average(o => o.X);
double centerY = Points.Average(o => o.Y);
return new CPoint(0, centerX, centerY);
}
/// <summary>
/// 计算旋转角
/// </summary>
/// <param name="center"></param>
/// <param name="point"></param>
/// <returns></returns>
public double CalculateAngle(CPoint center, CPoint point)
{
double deltaY = point.Y - center.Y;
double deltaX = point.X - center.X;
double angleInRadians = Math.Atan2(deltaY, deltaX);
double angleInDegrees = angleInRadians * (180.0 / Math.PI);
return angleInDegrees;
}
/// <summary>
/// 判断两个距离是否相等
/// </summary>
/// <param name="d1"></param>
/// <param name="d2"></param>
/// <returns></returns>
public bool Equal(double d1, double d2)
{
if (Math.Abs(d2 - d1) < 0.000001)
{
return true;
}
return false;
}
/// <summary>
/// 计算两点之间的距离
/// </summary>
/// <param name="pnt1"></param>
/// <param name="pnt2"></param>
/// <returns></returns>
public double Distance(CPoint pnt1, CPoint pnt2)
{
double a = pnt1.X - pnt2.X;
double b = pnt1.Y - pnt2.Y;
double c = Math.Sqrt(a * a + b * b);
return c;
}
/// <summary>
/// 判断两个正方形是否是同一个正方形
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (obj == null) return false;
if (obj.GetType() != typeof(CSqure)) return false;
var val = (CSqure)obj;
if (this.ToString() == obj.ToString())
{
return true;
}
return false;
}
/// <summary>
/// 格式化正方形对象
/// </summary>
/// <returns></returns>
public override string ToString()
{
var temps = Points.OrderBy(o => o.Index);
return string.Join("-", temps.Select(o => o.Index));
}
/// <summary>
/// 根据点获取所有正方形
/// </summary>
/// <param name="Points"></param>
/// <returns></returns>
public static List<CSqure> GetAllSqures(List<CPoint> Points)
{
List<CSqure> Squres = new List<CSqure>();
for (int i = 0; i < Points.Count(); i++)
{
for (int j = 0; j < Points.Count(); j++)
{
for (int k = 0; k < Points.Count(); k++)
{
for (int l = 0; l < Points.Count(); l++)
{
CSqure squre = new CSqure(Points[i], Points[j], Points[k], Points[l]);
if (squre.IsSqure())//判断是不是正方形
{
bool isExist = false;
foreach (var item in Squres)
{
if (item.ToString() == squre.ToString()) //判断是不是已经存在
{
isExist = true;
break;
}
}
if (!isExist)//没有找到过则添加到列表
{
Squres.Add(squre);
}
}
}
}
}
}
Squres = Squres.OrderBy(o => o.C).ThenBy(o => o.CenterY).ThenBy(o => o.CenterX).ToList();
return Squres;
}
}
public List<CPoint> Points = new List<CPoint>();
public List<CSqure> Squres = new List<CSqure>();
Timer timer = new Timer();
public Form1()
{
InitializeComponent();
this.DoubleBuffered = true;
timer.Tick += Timer_Tick;
timer.Interval = 600;
timer.Start();
int index = 1;
//Points.Add(new CPoint(index++, 1, 1, 0));
//Points.Add(new CPoint(index++, 1, 2, 0));
Points.Add(new CPoint(index++, 1, 3, 0));
Points.Add(new CPoint(index++, 1, 4, 0));
//Points.Add(new CPoint(index++, 1, 5, 0));
//Points.Add(new CPoint(index++, 1, 6, 0));
//Points.Add(new CPoint(index++, 2, 1, 0));
//Points.Add(new CPoint(index++, 2, 2, 0));
Points.Add(new CPoint(index++, 2, 3, 0));
Points.Add(new CPoint(index++, 2, 4, 0));
//Points.Add(new CPoint(index++, 2, 5, 0));
//Points.Add(new CPoint(index++, 2, 6, 0));
Points.Add(new CPoint(index++, 3, 1, 0));
Points.Add(new CPoint(index++, 3, 2, 0));
Points.Add(new CPoint(index++, 3, 3, 0));
Points.Add(new CPoint(index++, 3, 4, 0));
Points.Add(new CPoint(index++, 3, 5, 0));
Points.Add(new CPoint(index++, 3, 6, 0));
Points.Add(new CPoint(index++, 4, 1, 0));
Points.Add(new CPoint(index++, 4, 2, 0));
Points.Add(new CPoint(index++, 4, 3, 0));
Points.Add(new CPoint(index++, 4, 4, 0));
Points.Add(new CPoint(index++, 4, 5, 0));
Points.Add(new CPoint(index++, 4, 6, 0));
//Points.Add(new CPoint(index++, 5, 1, 0));
//Points.Add(new CPoint(index++, 5, 2, 0));
Points.Add(new CPoint(index++, 5, 3, 0));
Points.Add(new CPoint(index++, 5, 4, 0));
//Points.Add(new CPoint(index++, 5, 5, 0));
//Points.Add(new CPoint(index++, 5, 6, 0));
//Points.Add(new CPoint(index++, 6, 1, 0));
//Points.Add(new CPoint(index++, 6, 2, 0));
Points.Add(new CPoint(index++, 6, 3, 0));
Points.Add(new CPoint(index++, 6, 4, 0));
//Points.Add(new CPoint(index++, 6, 5, 0));
//Points.Add(new CPoint(index++, 6, 6, 0));
Squres = CSqure.GetAllSqures(Points);
}
private int drawIndex = 0;
private void Timer_Tick(object sender, EventArgs e)
{
drawIndex++;
if(drawIndex>Squres.Count())
{
drawIndex = 1;
}
Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
foreach (var item in Points)
{
e.Graphics.FillEllipse(SystemBrushes.GrayText, item.DrawCircle()) ;
}
return;
int indexr = 0;
int indexg = 0;
int indexb = 0;
int start = 127;
int r = start;
int g = start;
int b = start;
int step = 40;
int index=0;
foreach (var item in Squres)
{
index++;
indexr += step;
if(index != drawIndex)
{
continue;
}
if(indexr>255- start)
{
indexg += step;
if (indexg > 255 - start)
{
indexb += step;
if (indexb > 255 - start)
{
indexb = 0;
indexg = 0;
indexb = 0;
}
indexg = 0;
}
indexr = 0;
}
var color = Color.FromArgb(255, r + indexr, g + indexg, b + indexb);
var color2 = Color.FromArgb(255,255- r - indexr, 255 - g - indexg, 255 - b - indexb);
using (Pen p = new Pen(color))
using (Brush b2 = new SolidBrush(color))
using (Brush b3 = new SolidBrush(color2))
{
e.Graphics.FillPolygon(b2, item.DrawSqure());
e.Graphics.DrawPolygon(p, item.DrawSqure());
var size = e.Graphics.MeasureString($"{index}",this.Font);
e.Graphics.DrawString($"{index}",this.Font, b3, item.DrawCenter(size));
e.Graphics.DrawString($"{index}.边长:{item.C.ToString("0.00")}", this.Font, b3, new PointF(50,53));
}
}
base.OnPaint(e);
}
}
}