原题地址
简单说一下题意,题中定义的那个要求的值是能包含k的点的最小的子矩阵的面积,考试的时候没想出来,一看到题就蒙了,考完回来查题解原来是用尺取法,然后看了看思路,自己写了一发,简单说一下思路,就是先求出每个点道最左上角点之间有多少个点,然后枚举上界和下界,对上界下界之间的尺取就行了.
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
int rec[500][500];
bool cal(int s,int e,int h1,int h2,int t){ //计算上界和下界,左右端点之间的点数是否大于k
if(rec[h1][e]-rec[h1][s]-rec[h2][e]+rec[h2][s]>=t){
return true;
}
else{
return false;
}
}
int main(){
int n,m,k,h;
while(~scanf("%d%d%d",&n,&m,&k)){
if(n==0&&m==0&&k==0){
break;
}
char map[500][500];
int i,j,mins=99999999;
for(i=1;i<=n;i++){
scanf("%s",map[i]+1);
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
rec[i][j]=rec[i][j-1];
if(map[i][j]=='.'){
rec[i][j]++;
}
}
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
rec[j][i]=rec[j][i]+rec[j-1][i];
}
}
// for(i=1;i<=n;i++){ //Debug
// for(j=1;j<=m;j++){
// printf("%d ",rec[i][j]);
// }
// printf("\n");
// }
//int s1,s2;
for(i=0;i<=n;i++){ //枚举上界
for(j=i+1;j<=n;j++){ //枚举下界
int end=0;
for(h=1;h<=m;h++){ //枚举列
if(rec[j][h]-rec[i][h]>=k){
while(cal(end, h, j, i, k)){
mins=min(mins,(j-i)*(h-end));
end++;
}
}
}
}
}
printf("%d\n",mins);
memset(rec, 0, sizeof(rec));
}
return 0;
}