-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path1194B_YetAnotherCrosses.cpp
More file actions
90 lines (83 loc) · 3.88 KB
/
1194B_YetAnotherCrosses.cpp
File metadata and controls
90 lines (83 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
* Created by ishaanjav
* github.com/ishaanjav
* Codeforces Solutions: https://github.com/ishaanjav/Codeforces-Solutions
*/
#include <iostream>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
int q;
cin >> q;
while (q--) {
int rows, cols;
cin >> rows >> cols;
// Grid is the grid we read from input
string grid[rows];
for (int i = 0; i < rows; i++) cin >> grid[i];
// Except for the Input, Output, and min function, the rest of the code is exactly the same as Java
// In the worst case our answer is rows + cols - 1. We do -1 because we don't want to count the center square twice.
int ans = rows + cols - 1;
// EXPLANATION OF SOLUTION
// To solve this problem, we have to go through every single position in our grid
// and count the number of X's required to make a cross. This is pretty much the only way to do it.
// we do this by treating each position as the center of our cross and counting the # of X's missing in its row and column
// But, if we do this trivially, we'd have an O(n^3) time complexity which wouldn't pass
// It is O(n^3) because there are n^2 elements to go through and it takes linear time to go through that element's row and column.
// ----
// The idea is to do precomputations to bring it down to O(n^2)
// The way that this works is:
// for position (0,0) we need to know the # of crosses in row 0 and column 0.
// for position (0,1) we need to know the # of crosses in row 0 and column 1.
// for position (0,2) we need to know the # of crosses in row 0 and column 2.
// ......
// Do you see that for all those positions we need to know the # of crosses in row 0?
// Rather than repeatedly counting this, beforehand we go through the grid array and count the # of xs in each row
// We repeat the same thing with columns.
// And we store these values in arrays.
// Now, all we have to do is for each element in our grid.
// The number of x's required to make a cross is
// rows + cols - # of X's in row - # of X's in column
// To get the # of X's in the rows and columns, we can use the arrays we created from precomputation
// there is one special case: if the current element is a . not an X, then we have to make that an X as well so we add 1 to the number above
// And our answer is the minimum out of that equation for every element
// See the code below!
// rowFilled[row] = # of X's in row
// colFilled[column] = # of X's in column
int rowFilled[rows], colFilled[cols];
for (int i = 0; i < rows; i++) {
int counter = 0;
for (int j = 0; j < cols; j++) {
if (grid[i][j] != '.') {
counter++;
}
}
rowFilled[i] = counter;
}
for (int j = 0; j < cols; j++) {
int counter = 0;
for (int i = 0; i < rows; i++) {
if (grid[i][j] != '.') {
counter++;
}
}
colFilled[j] = counter;
}
// After doing precomputations, for each position calculate the minimum # of X's we need to add to make a cross
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == '.') {
ans = min(ans, rows + cols - (rowFilled[i] + colFilled[j] + 1));
} else {
ans = min(ans, rows + cols - (rowFilled[i] + colFilled[j]));
}
// 0 is the lowest we can go so break.
if (ans == 0) break;
}
if (ans == 0) break;
}
//Print answer
cout << ans << endl;
}
}