“Shopee杯” 武漢大學(網絡預選賽)D - DIY Masks at Home

“Shopee杯” 武漢大學(網絡預選賽)D - DIY Masks at Home

題目鏈接:Click

時間限制:C/C++ 5秒,其他語言10秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

During the outbreak of COVID-19, xyjj has to stay at home for a long time, which is because he doesn’t have any mask. If he wants to go outside, he must wear a mask to avoid being infected. But if he wants to have a mask, he must go outside to buy one!

Finally, he came up with a solution: Why not DIY at home! Quickly he found the materials required: scissors, needle and threads, and a large piece of cloth (cut from the curtains of his room). To make a mask, he need to cut out a piece of square cloth, and other part of the mask can be easily made so it doesn’t matter. The original cloth can be regarded as a rectangle of n * m cm2, which is made up of 1×1 small colorful squares as the image showing below.

(That’s a typical programmer’s style, isn’t it?)
在這裏插入圖片描述
However, xyjj doesn’t want his mask to be colorful, so he want the square he selected to have only one single color. Meanwhile, he wants the square to be cut out as large as possible, or the mask might not be able to cover his face. Can you help him with this problem?

輸入描述

The input consists of several test cases. The first line contains an integer T, the number of test cases.
For each test case:
The first line will be two integers n, m, which describe the size of the cloth.
For the next n lines, each line will be a string of m upper-case Latin letters, which describe the pattern of the cloth. Each letter refers to a kind of color and places which have the same letters also have the same color
Here it’s guaranteed that .1 ≤ n, m ≤ 2000 and ∑n, ∑m ≤ 2000 for all test cases.

輸出描述

For each test case, print one integer ansans in a single line, which is the maximum length of the square we can get. (i.e the result square’s size will be ans*ans cm2).

樣例輸入#1

1
3 4
AABB
AACC
CCCC

樣例輸出#1

2

題意

從輸入矩陣中,找到最大方形矩陣(同色),輸出邊長。

分析

別看 n 只有2000,如果暴力的話會變成 2000*2000*2000*2000*k
所以,其實大部分關於最大子矩陣問題,都是dp啦

這題思路還是比較清晰的,關鍵在於如何尋找狀態轉移方程,(好吧,dp都這樣)

如此定義:dp[i][j] 表示以第 i 行 第 j 列元素爲右下角的 子矩陣最大邊長
(當然實際上我是從0 0 開始計數的)
狀態轉移方程:
①若map[i][j] != map[i-1][j-1]
dp[i][j]=1,此時只有一個元素

②若map[i][j] == map[i-1][j-1]
此時計算向上和向左能拓展的最大長度 t
if (t>dp[i-1][j-1]) dp[i][j] = dp[i-1][j-1]+1 拓展一格
否則
dp[i][j]=t; 自立門戶
如:
AAAB
AAAB
AAAA
BBAA
對於最後一個元素,t=2,不能拓展,只能自立門戶

"Talk is Cheap. Show me the Code."

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 2005;
typedef long long ll;
char map[maxn][maxn];
int dp[maxn][maxn];
int main(void)
{
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, m;
        scanf("%d %d", &n, &m);
        memset(dp, 0, sizeof(dp));
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                scanf(" %c", &map[i][j]);
        for (int i = 0; i < n; i++)//初值
            dp[i][0] = 1;
        for (int j = 0; j < m; j++)
            dp[0][j] = 1;
        int ans = 1;
        for(int i=1;i<n;i++)
            for (int j = 1; j < m; j++) {
                if (map[i][j] != map[i - 1][j - 1]) {
                    dp[i][j] = 1;
                    continue;
                }
                int l = j, u = i, t = 0;
                while (l >= 0 && u >= 0 && map[i][l] == map[i][j] && map[u][j] == map[i][j])
                    l--, u--, t++;//向上,向左拓展
                if (t > dp[i - 1][j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = t;
                ans = max(ans, dp[i][j]);
            }
        printf("%d\n", ans);
    }
    return 0;
}

突然發現這題給了5s,很給面子
感謝 sjjda 指出錯誤

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章