题意:
给定n*m的图,和一个整数k, 图由’X‘和’.‘组成,现在要求你找到一个面积最小的子矩阵,满足子矩阵中的’.'不少于k个。 输出最小面积。
数据范围:n,m<=300,k<=n*m
解法:
考虑1*m的矩阵,如果要求找到一个最小的子矩阵,满足不少于k个, 可以直接尺取。
那么n*m怎么做呢,枚举行i和行j,将[i,j]行合并为一行,每一列是[i,j]列的权值和。 然后就变成上面的情况了,进行尺取即可。
枚举i,j的复杂度为O(n2),尺取O(n),总复杂度O(n3)
code:
#include<bits/stdc++.h>
using namespace std
;
#define int long long
#define ll long long
#define PI pair<int,int>
const int maxm
=305;
char s
[maxm
][maxm
];
int sum
[maxm
][maxm
];
int temp
[maxm
];
int a
[maxm
];
int n
,m
,k
;
signed main(){
ios
::sync_with_stdio(0);
while(cin
>>n
>>m
>>k
){
if(!(n
+m
+k
))break;
for(int i
=1;i
<=n
;i
++){
for(int j
=1;j
<=m
;j
++){
cin
>>s
[i
][j
];
}
}
for(int i
=1;i
<=n
;i
++){
for(int j
=1;j
<=m
;j
++){
sum
[i
][j
]=sum
[i
][j
-1]+sum
[i
-1][j
]-sum
[i
-1][j
-1]+(s
[i
][j
]=='.');
}
}
int ans
=n
*m
;
for(int i
=1;i
<=n
;i
++){
for(int j
=i
;j
<=n
;j
++){
for(int t
=1;t
<=m
;t
++){
temp
[t
]=sum
[j
][t
]-sum
[i
-1][t
];
}
int p
=1;
for(int t
=1;t
<=m
;t
++){
while(temp
[t
]-temp
[p
-1]>=k
){
ans
=min(ans
,(j
-i
+1)*(t
-p
+1));
p
++;
}
}
}
}
cout
<<ans
<<endl
;
}
return 0;
}