枚举
1.特点:一一列举
2.要点:不重复不遗漏
但是不充复不遗漏只能保证把题目求出来,但可能会被时间卡住
3.优化:把多余的操作去掉,减少枚举次数
①选择合适的枚举对象
②选择合适的枚举方向——方便排除非法和不是最优的情况
③选择合适的数据维护方法——方便转化问题

最大正方形 --题目和图片来自https://blog.csdn.net/qq_46009744/article/details/106142716
题目描述:
在一个N*N(N<=100)矩阵中求一个最大的正方形使得该正方形的四个顶点都是有字符“#”构成。

暴力枚举四个点的话,是个4重循环,n^4 , 如果矩阵中每个点都是#, 就是 1e16, 肯定超时。

为了优化枚举,可以优化枚举对象,思考几个点可以确定一个正方形?
–正方形可以由两个点唯一确定
–长方形可以由三个点唯一确定

(B点和D点都可以通过A,B的坐标所表示)

我们枚举A,B这两个点的坐标,都是#,然后直接算出B,D的坐标,如果B,D的点都是#,则是正方形,如果不是#,则说明A,C这对对角线不行。

代码的实现参考了:https://blog.csdn.net/qq_46009744/article/details/106142716

pair存点,set来找点,枚举 的想法和步骤都很值得学习。值得注意的通过A,C点找到B,D点的位置是需要讨论的。

#include<bits/stdc++.h>
using namespace std;
const int N=110;
char mp[110][110];
int x[N*N];
int y[N*N];
typedef pair<int,int> Point;
set<Point > pset;
int main()
{
   
	int n,k=0;
	while(cin >> n) {
   
		for(int i=0; i<n; i++) {
   
			scanf("%s",mp[i]);
			for(int j=0; j<n; j++) {
   
				if(mp[i][j]=='#') {
   
					x[k]=i+1;
					y[k]=j+1;
					pset.insert(make_pair(x[k],y[k]));
					k++;
				}
			}
		}
		int ans=0;
		for(int i=0; i<n; i++) 
			for(int j=i+1; j<n; j++) {
   
				int mx=(x[i]+x[j])/2;	int dx=abs(x[i]-x[j]);
				int my=(y[i]+y[j])/2;	int dy=abs(y[i]-y[j]);
				int sg=((x[i]-x[j])*(y[i]-y[j])<0 ? -1 : 1);
				if(pset.count(make_pair(mx+dy*sg,my-dx))!=0 && pset.count(make_pair(mx-dy*sg,my+dx))!=0) {
   
					int dis=(x[i]-x[j])*(x[i]-x[j])-(y[i]-y[j])*(y[i]-y[j]);
					dis/=2;
					ans=max(dis,ans);	 
				}
			}
		cout<<sqrt(ans)<<endl;
	}
}