最大正方形(枚舉)

枚舉算法

1.特點:一一列舉
2.要點:不重複不遺漏
但是不充復不遺漏只能保證把題目求出來,但可能會被時間卡住
3.優化:把多餘的操作去掉,減少枚舉次數
①選擇合適的枚舉對象
②選擇合適的枚舉方向——方便排除非法和不是最優的情況
③選擇合適的數據維護方法——方便轉化問題

最大正方形

題目描述:

在一個N*N(N<=100)矩陣中求一個最大的正方形使得該正方形的四個頂點都是有字符“#”構成。
在這裏插入圖片描述

解題思路:

首先我們可以暴力做法:枚舉四個#,即寫一個四重的for循環,去看這個四個#,把這四個#找出來之後去看他是否能組成一個正方形。
他的時間複雜度顯然是O(#個數的四次方)最壞情況下全是#,即N的平方,那麼就是O(N的八次方),N<=100,那麼爲10的16次方,顯然是不行的,百分之百tle。

那我們思考幾個點能確定一個正方形?

1.兩個點確定一個正方形,然後判斷其餘兩個點是否爲“#”

2.三個點確定一個矩形,若矩形邊平行於座標軸,則只需要兩個點

在這裏插入圖片描述
我們就去枚舉A、C這兩個點,都是有#的,然後直接算出B、D兩點的座標,去看一下他是不是#,如果是#,證明是正方形,如果不是#,則不是正方形,AC這條對角線不行。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int N=102;
char s[N][N]; 
int n;
/*
struct node{
	int x,y;
}dot[N*N];
*/
int x[N*N],y[N*N];
typedef pair<int,int> Point;
set<Point> pset;
int main()
{
	ios::sync_with_stdio(false);
	while(cin>>n){
		int k=0;
		pset.clear();
		for(int i=0;i<n;i++)
		{	
		scanf("%s",s[i]);
			for(int j=0;j<n;j++)
			{
				if(s[i][j]=='#'){
					x[k]=i+1;
					y[k]=j+1;
					//cout<<i<<" "<<j<<endl; 
					pset.insert(make_pair(x[k],y[k]));
					k++;
				}
			}
		}
		int cnt=0;//邊長的平方 
		for(int i=0;i<k;i++)
		{
			for(int j=i+1;j<k;j++)
			{
				int mx=x[i]+x[j],dx=max(x[i],x[j])-min(x[i],x[j]);
				int my=y[i]+y[j],dy=max(y[i],y[j])-min(y[i],y[j]);
				if((mx+dy)&1||(my+dx)&1)	continue;
				int sg=((x[i]-x[j])*(y[i]-y[j])<0)?1:-1;
				if(pset.count(make_pair((mx+dy)/2,(my+sg*dx)/2))&&
				pset.count(make_pair((mx-dy)/2,(my-sg*dx)/2)))
				{
					int dis=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
					dis=dis/2;
					cnt=max(cnt,dis);
				}
			}
		}
		cout<<sqrt(cnt)<<endl; 
	}
	return 0;
 } 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章