#P1448. 第3题-小红的棋盘
-
1000ms
Tried: 433
Accepted: 70
Difficulty: 6
所属公司 :
京东
时间 :2023年8月12日
-
算法标签>暴力枚举
第3题-小红的棋盘
思路:枚举+trick
这道题首先我们发现只要固定正方形两条相邻边,就可以得到这个正方形的具体信息。 但是直接固定两条边需要枚举三个点,复杂度比较高。
我们完全可以枚举一条边,然后将这条边顺时针或者逆时针旋转90度,从而实现固定两条边。这样只需要枚举两个点即可。
然后一个正方形按照这样的寻找策略会被找到4次,因此最后答案要除4。
时间复杂度:O(n2m2)
代码
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<vector<char>> mp(n, vector<char>(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> mp[i][j];
}
}
int ans = 0;
for (int x1 = 0; x1 < n; x1++) {
for (int y1 = 0; y1 < m; y1++) {
if (mp[x1][y1] == 'X') {
for (int x2 = 0; x2 < n; x2++) {
for (int y2 = 0; y2 < m; y2++) {
if (x2 == x1 && y2 == y1) continue;
if (mp[x2][y2] == 'X') {
int dx = x2 - x1;
int dy = y2 - y1; // 按照向量顺时针或者逆时针
int x3 = x1 - dy; // 求到第三第四个点
int y3 = y1 + dx;
int x4 = x3 + dx;
int y4 = y3 + dy;
if (0 <= x3 && x3 < n && 0 <= y3 && y3 < m && 0 <= x4 && x4 < n && 0 <= y4 && y4 < m && mp[x3][y3] == 'X' && mp[x4][y4] == 'X') {
ans++; // 符合要求就计数
}
}
}
}
}
}
}
cout << ans / 4 << "\n"; // 答案数除4
return 0;
}
python
n, m = map(int, input().split())
mp = [list(input()) for i in range(n)]
ans = 0
for x1 in range(n):
for y1 in range(m):
if mp[x1][y1] == 'X':
for x2 in range(n):
for y2 in range(m):
if x2 == x1 and y2 == y1:continue
if mp[x2][y2] == 'X':
dx = x2 - x1
dy = y2 - y1 # 按照向量顺时针或者逆时针
x3, y3 = x1 - dy, y1 + dx # 求到第三第四个点
x4, y4 = x3 + dx, y3 + dy
if 0 <= x3 < n and 0 <= y3 < m and 0 <= x4 < n and 0 <= y4 < m and mp[x3][y3] == 'X' and mp[x4][y4] == 'X':
ans += 1 # 符合要求就计数
print(ans // 4) # 答案数除4
Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
char[][] mp = new char[n][m];
for (int i = 0; i < n; i++) {
String line = scanner.next();
for (int j = 0; j < m; j++) {
mp[i][j] = line.charAt(j);
}
}
int ans = 0;
for (int x1 = 0; x1 < n; x1++) {
for (int y1 = 0; y1 < m; y1++) {
if (mp[x1][y1] == 'X') {
for (int x2 = 0; x2 < n; x2++) {
for (int y2 = 0; y2 < m; y2++) {
if (x2 == x1 && y2 == y1) {
continue;
}
if (mp[x2][y2] == 'X') {
int dx = x2 - x1;
int dy = y2 - y1; // 按照向量顺时针或者逆时针
int x3 = x1 - dy; // 求到第三第四个点
int y3 = y1 + dx;
int x4 = x3 + dx;
int y4 = y3 + dy;
if (0 <= x3 && x3 < n && 0 <= y3 && y3 < m && 0 <= x4 && x4 < n && 0 <= y4 && y4 < m && mp[x3][y3] == 'X' && mp[x4][y4] == 'X') {
ans++; // 符合要求就计数
}
}
}
}
}
}
}
System.out.println(ans / 4); // 答案数除4
}
}
题目内容
小红喜欢玩王者,尤其擅长奕星,并且时常沉迷于用奕星的大招困住敌人。
所以他设计了一个巨大棋局,棋盘中的格子只有两种可能,如果是 ′X′ 则表示这个格子可以作为棋盘的一个边角,如果是 ′.′ 则表示不可以。
小红要按这个棋局的情况去进行奕星的大招练习,即选择四个为 ′X′ 的不同格子,这四个格子可以构成一个正方形棋盘。
现在小红想问你,可以获得多少个不同的正方形棋盘。
两个棋盘相同当且仅当四个边角都可以完全对应上,否则就是不同的正方形棋盘。
输入描述
第一行,一个正整数n,m,代表巨大棋局的大小
接下来n行,每行一个长度为m的字符串,仅包含′.′和′X′。
1≤n,m≤50
输出描述
一个整数,表示可以获得的不同棋盘的数量。
样例
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
4 4
XX.X
XX.X
.X.X
..X.
输出
2
说明 第一个正方形棋盘为:(1,2),(3,2),(1,4),(3,4)
第二个正方形棋盘为:(1,1),(1,2),(2,1),(2,2)