TZOJ2906: Largest Submatrix of All 1’s
描述
Given a m-by-n (0,1)-matrix, of all its submatrices of all 1’s which is the largest? By largest we mean that the submatrix has the most elements.
输入
The input contains multiple test cases. Each test case begins with m and n (1 ≤ m, n ≤ 2000) on line. Then come the elements of a (0,1)-matrix in row-major order on m lines each with n numbers. The input ends once EOF is met.
输出
For each test case, output one line containing the number of elements of the largest submatrix of all 1’s. If the given matrix is of all 0’s, output 0.
样例输入
2 2
0 0
0 0
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
样例输出
0
4
解题思路
很明显这是求二维子矩阵最大和的题目,但又有点特别他只有0和1。题目给出的矩阵较大,使用朴素O(N ^ 4)或者O(N ^ 3)的解法是不可行的。所以考虑特殊解法,请参考。
O(N ^ 4)超时
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define inf 0x3f3f3f3f
#define IOS ios::sync_with_stdio(0), cin.tie(0)
const ll N = 1e3 * 2 + 5;
inline ll read() {
ll x=0,f=1;char c=getchar();
while (!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
ll n, m, a[N][N];
ll get(ll x, ll y, ll x2, ll y2) {
return a[x2][y2] - a[x - 1][y2] - a[x2][y - 1] + a[x - 1][y - 1];
}
void solve() {
while (~scanf("%d %d", &n, &m)) {
memset(a, 0, sizeof a);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
ll x; x = read();
a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + x;
}
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
for (int l = 1; l <= i; ++l) {
for (int k = 1; k <= j; ++k) {
ll x = get(l, k, i, j);
ans = max(ans, x);
}
}
}
}
cout << ans << '\n';
}
}
int main( ){
// IOS;
// ll t; cin >> t;
ll t = 1;
while (t--) solve();
return 0;
}
O(N ^ 3)超时(最大子段和思想)
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define inf 0x3f3f3f3f
#define IOS ios::sync_with_stdio(0), cin.tie(0)
const ll N = 1e3 * 2 + 5;
inline ll read() {
ll x=0,f=1;char c=getchar();
while (!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
ll n, m, a[N][N];
ll get(ll x, ll y, ll x2, ll y2) {
return a[x2][y2] - a[x - 1][y2] - a[x2][y - 1] + a[x - 1][y - 1];
}
void solve() {
while (~scanf("%d %d", &n, &m)) {
memset(a, 0, sizeof a);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
ll x; x = read();
a[i][j] = a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1] + x;
}
}
ll ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; ++j) {
vector<ll> dp(n + 1);
for (int k = 1; k <= m; ++k) {
ll x = get(i, k, j, k);
dp[k] = max(x, dp[k - 1] + x);
ans = max(ans, dp[k]);
}
}
}
cout << ans << '\n';
}
}
int main( ){
// IOS;
// ll t; cin >> t;
ll t = 1;
while (t--) solve();
return 0;
}
代码
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define inf 0x3f3f3f3f
#define IOS ios::sync_with_stdio(0), cin.tie(0)
const ll N = 1e3 * 2 + 5;
inline ll read() {
ll x=0,f=1;char c=getchar();
while (!isdigit(c)) {if(c=='-')f=-1;c=getchar();}
while (isdigit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
ll n, m;
void solve() {
while (~scanf("%d %d", &n, &m)) {
vector<ll> a(m + 2), b(m + 1);
ll ans = 0;
stack<ll> st;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
ll x; x = read();
if(x == 1) ++ b[j];
else b[j] = 0;
a[j] = b[j];
}
a[m + 1] = -inf;
for (int j = 1; j <= m + 1; ++j) {
if (st.empty() || a[j] >= a[st.top()]) {
st.push(j);
} else {
ll top = 0;
while (!st.empty() && a[j] < a[st.top()]) {
top = st.top();
st.pop();
ans = max(ans, (j - top) * a[top]);
}
st.push(top);
a[top] = a[j];
}
}
}
cout << ans << '\n';
}
}
int main( ){
// IOS;
// ll t; cin >> t;
ll t = 1;
while (t--) solve();
return 0;
}