1. 程式人生 > >習題4-2 正方形

習題4-2 正方形

題目:
在這裡插入圖片描述
大意就是給出n和m,構造N^2點數的正方形並輸入m條指令:
H i j 代表橫向連線座標為 (i, j)和座標為 (i, j + 1)的兩點;
V i j 代表縱向連線座標為 (i, j)和座標為 (i + 1, j)的兩點。
問最終能連成不同邊長的正方形各多少個。

解析:
對於不同的指令,我想到用兩個陣列V[n][n]和H[n][n]來保留操作,對於每個點的座標,分別統計以它為起點的不同邊長正方形的個數,最後加和即可。假設最初兩個陣列全為0,聯通則置1,那麼判斷應該為:

if (!H[i][j + k] || !H[i + len][j + k]) {
	flag = 0;break;
}
if (!V[i + k][j] || !V[i + k][j + len]) {
	flag = 0;break;
}

可是真到了程式設計卻不能越過邏輯的坎兒。看了一下網上其他人的程式碼,才發現是自己的邏輯出錯了。正確的想法應該是:對於不同邊長的正方形個數進行依次統計(這是最外層迴圈,這樣才能有i+len<=n的限制條件),一個正方形如果完整,那麼它的每條邊都存在,因此在最內層迴圈遍歷它的每條邊,只要有一條邊不存在即可退出,否則計數。

程式碼:

//習題4-2 正方形
#include<iostream>
#include<Windows.h>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<ctype.h>
#include<cmath>
#define MAXN 10
using namespace std;
int H[MAXN][MAXN], V[MAXN][MAXN];
int main()
{
	int i, j, k, n, m, x, y, len;
	int flag = 1;
	int cnt = 0, sum = 0;
	char ch;
	cin >> n >> m;
	memset(V, 0, sizeof(V));
	memset(H, 0, sizeof(H));
	while(m--)
	{
		getchar();
		ch = getchar();
		scanf("%d%d", &x, &y);
		if (ch == 'V') V[x][y] = 1;
		else H[x][y] = 1;
	}
	for (len = 1;len <= n;len++)	//正方形的邊長範圍
	{
		cnt = 0;
		for (i = 1;i + len <= n;i++)
		{
			for (j = 1;j + len <= n;j++)
			{
				flag = 1;
				for (k = 0;k < len;k++)	//遍歷每條邊(個點),只要有不連通的就退出
				{
					if (!H[i][j + k] || !H[i + len][j + k]) {	//上與下、左與右座標之間差的是一個邊長
						flag = 0;break;
					}
					if (!V[i + k][j] || !V[i + k][j + len]) {
						flag = 0;break;
					}
				}
				cnt += flag;	//對於每種邊長的個數
			}
		}
		sum += cnt;	//總個數
		if (cnt) printf("%d square (s) of size %d\n", cnt, len);
	}
	system("pause");
	return 0;
}