Loading

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;
}
posted @ 2022-05-13 01:27  dgsvygd  阅读(51)  评论(0编辑  收藏  举报