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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
static int numRows, numCols;
static long long limitK;
static vector<vector<long long>> prefixSum; // 1-based inclusive prefix sums
inline long long sumRect(int topRow, int leftCol, int bottomRow, int rightCol) {
if (topRow > bottomRow || leftCol > rightCol) return 0LL;
return prefixSum[bottomRow][rightCol]
- prefixSum[topRow - 1][rightCol]
- prefixSum[bottomRow][leftCol - 1]
+ prefixSum[topRow - 1][leftCol - 1];
}
// Keep columns [keepLeft, keepRight], end with 1 x (keepRight-keepLeft+1)
bool canEndWithHorizontalStripe(int keepLeft, int keepRight) {
int top = 1, bottom = numRows, left = 1, right = numCols;
const int targetWidth = keepRight - keepLeft + 1;
const int stepsBeforeLast = (numRows + numCols) - targetWidth - 1;
for (int step = 0; step < stepsBeforeLast; ++step) {
// Prefer removing a row if possible
if (bottom - top + 1 > 1 && sumRect(top, left, top, right) <= limitK) { top++; continue; }
if (bottom - top + 1 > 1 && sumRect(bottom, left, bottom, right) <= limitK) { bottom--; continue; }
// Then remove columns only outside the target interval
if (left < keepLeft && sumRect(top, left, bottom, left) <= limitK) { left++; continue; }
if (right > keepRight && sumRect(top, right, bottom, right) <= limitK) { right--; continue; }
return false;
}
return sumRect(top, left, bottom, right) <= limitK;
}
// Keep rows [keepTop, keepBottom], end with (keepBottom-keepTop+1) x 1
bool canEndWithVerticalStripe(int keepTop, int keepBottom) {
int top = 1, bottom = numRows, left = 1, right = numCols;
const int targetHeight = keepBottom - keepTop + 1;
const int stepsBeforeLast = (numRows + numCols) - targetHeight - 1;
for (int step = 0; step < stepsBeforeLast; ++step) {
// Prefer removing a column if possible
if (right - left + 1 > 1 && sumRect(top, left, bottom, left) <= limitK) { left++; continue; }
if (right - left + 1 > 1 && sumRect(top, right, bottom, right) <= limitK) { right--; continue; }
// Then remove rows only outside the target interval
if (top < keepTop && sumRect(top, left, top, right) <= limitK) { top++; continue; }
if (bottom > keepBottom && sumRect(bottom, left, bottom, right) <= limitK) { bottom--; continue; }
return false;
}
return sumRect(top, left, bottom, right) <= limitK;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Input: k m n (as in the official statement)
long long kInput;
int mInput, nInput;
if (!(cin >> kInput >> mInput >> nInput)) return 0;
limitK = kInput;
numCols = mInput;
numRows = nInput;
prefixSum.assign(numRows + 1, vector<long long>(numCols + 1, 0));
for (int i = 1; i <= numRows; ++i) {
for (int j = 1; j <= numCols; ++j) {
long long v; cin >> v;
prefixSum[i][j] = v + prefixSum[i - 1][j] + prefixSum[i][j - 1] - prefixSum[i - 1][j - 1];
}
}
int best = INT_MAX;
// Horizontal final stripe (1 x width)
{
int l = 1, r = 1;
while (true) {
bool ok = canEndWithHorizontalStripe(l, r);
if (ok) best = min(best, numRows + numCols - (r - l + 1));
if (l == numCols && r == numCols) break;
if (r == numCols) l++;
else if (l == r) r++;
else if (ok) r++;
else l++;
}
}
// Vertical final stripe (height x 1)
{
int t = 1, b = 1;
while (true) {
bool ok = canEndWithVerticalStripe(t, b);
if (ok) best = min(best, numRows + numCols - (b - t + 1));
if (t == numRows && b == numRows) break;
if (b == numRows) t++;
else if (t == b) b++;
else if (ok) b++;
else t++;
}
}
cout << best << '\n';
return 0;
}
|