HDU-1937 Finding Seats
Finding Seats
方格中只有数字 1 和 0,求最小的矩阵,使得其和大于等于 k
尺取
首先思考暴力,枚举行和列的起点和终点,时间复杂度是 \(O(n^4)\),显然不可行
接下来考虑优化,如果只是一个一维的,题目转化为,求一个连续的区间,使得其和大于等于 k
上述这个问题一眼可以看出能够使用尺取
因此针对这题,可以将二维转化成为一维,利用前缀和,首先枚举一个维度的起点和终点,然后用尺取计算另一个维度,和的计算用前缀和计算即可,时间复杂度为 \(O(n^3)\)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <queue>
#include <functional>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <deque>
#include <stack>
using namespace std;
typedef long long ll;
#define pii pair<int, int>
const ll maxn = 310;
const ll inf = 1e17 + 10;
char gra[maxn][maxn];
int num[maxn][maxn];
int main()
{
int n, m, k;
while(scanf("%d%d%d", &n, &m, &k) != EOF && (n | m | k))
{
for(int i=1; i<=n; i++)
scanf("%s", gra[i] + 1);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
num[i][j] = gra[i][j] == '.';
num[i][j] = num[i][j] + num[i][j-1];
}
}
int ans = n * m;
for(int i=1; i<=m; i++)
{
for(int j=i; j<=m; j++)
{
int l = 1, r = 1, now = 0;
while(1)
{
while(r <= n && now < k)
{
now += (num[r][j] - num[r][i-1]);
r++;
}
if(now < k) break;
ans = min(ans, (j - i + 1) * (r - l));
now -= (num[l][j] - num[l][i-1]);
l++;
}
}
}
printf("%d\n", ans);
}
return 0;
}