Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.84/25: Рейтинг темы: голосов - 25, средняя оценка - 4.84
2 / 2 / 0
Регистрация: 28.03.2020
Сообщений: 31
1

Найти прямоугольную область белого цвета состоящую из наибольшего количества ячеек

01.11.2020, 12:24. Показов 5246. Ответов 12

Author24 — интернет-сервис помощи студентам
В прямоугольной таблице клетки раскрашены в белый и черный цвета. Найти в ней прямоугольную область белого цвета, состоящую из наибольшего количества ячеек.

Входные данные:
Во входном файле INPUT.TXT записана сначала высота N, а затем ширина M таблицы (1≤N≤100, 1≤M≤100), а затем записано N строк по M чисел в каждой строке, где 0 означает, что соответствующая клетка таблицы выкрашена в белый цвет, а 1 — что в черный.

Выходные данные:
В выходной файл OUTPUT.TXT вывести одно число — количество клеток, содержащихся в наибольшем по площади белом прямоугольнике.

Примеры:
Ввод:
5 6
1 0 0 0 1 0
0 0 0 0 1 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0

Вывод:
9
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.11.2020, 12:24
Ответы с готовыми решениями:

Найти вероятность вытащить шарик белого цвета с первого раза
Подскажите, пожалуйста, решение следующей задачи: Имеем две корзины. В первой 5 шариков белого...

Найти вероятность того, что шар будет белого цвета
Из урны, содержащей n шаров неизвестного цвета, вынут один шар, оказавшийся белым. По возвращении...

Найти минимальное число вирусов с помощью которых можно заразить прямоугольную область
Здравствуйте, мне нужен совет по задаче: Для моделирования различных объектов часто применяются...

Найти вероятность того, что все три извлечённых шара оказались белого цвета
Добрый вечер. В первой урне два чёрных, восемь белых шаров; во второй урне семь белых, три чёрных...

12
n5
1 / 1 / 0
Регистрация: 28.08.2023
Сообщений: 32
20.07.2024, 16:08 2
Отвечаю поздно, но возможно помогу последователям!
1(как мне кажется самое важное). Эта задача сводится к задаче "Гистограмма".
1.1 "Гистограмма" - Задача, в которой имеется n небоскрёбов разно высоты, и нужно повесить ПРЯМОУГОЛЬНЫЙ плакат максимальной площади.
Например, n = 7, и высоты небоскрёбов такие 2 1 4 5 1 3 3.
Ответ на этот тест будет 8 (Плакат весит на небоскребах под номерами (3, 4) так, что 3ий небоскрёб полностью закрыт плакатом, а 4ый почти закрывает небоскрёб (не достаёт до 5 клетки) => 2 * 4 = 8).
Решение за O(N2)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000010
long long h[MAX];
int i, n, left, right;
long long area, res;
int main() {
    scanf("%d", &n);
    for (i = 1; i <= n; i++) cin >> h[i];
    res = 0;
    for (i = 1; i <= n; i++) {
        long long left = i, right = i;
        while (left > 1 && h[left - 1] >= h[i]) left--;
        while (right < n && h[right + 1] >= h[i]) right++;
        area = (right - left + 1) * h[i];
        if (area > res) res = area;
    }
    printf("%lld\n", res);
    return 0;
}
Есть решение быстрее O(N), напиши саму идею.
Пусть текущим является i-ый прямоугольник абсциссой i и высотой hi. Тогда:
Если его высота больше высоты прямоугольника на вершине стека, то заносим i-ый прямоугольник в стек.
Пока высота текущего прямоугольника (i, hi) меньше или равна высоте прямоугольника на вершине стека (x, hx) (то есть hi ≤ hx), то извлекаем прямоугольник из стека и вычисляем площадь максимального вписанного в гистограмму прямоугольника. Подозрительным на максимальный будет прямоугольник со сторонами i – x (он начинается в абсциссе x и заканчивается в абсциссе i – 1) и hx. Пусть последний вытолкнутый из стека прямоугольник ширины 1 имеет характеристики (j, hj) (hj ≥ hi). Тогда в стек следует положить пару (j, hi).

2. Ну так вот, теперь, когда мы умеем решать задачу про гистограмму, можно решить и про максимальный прямоугольник белого цвета.
Оказывается, что мы можем сделать цикл который будет идти сверху -> вниз по матрице и делать "небоскрёбы" из 0 в матрице.
Разберу подробней.
Есть изначальная матрица:
1 0 0 0 1 0
0 0 0 0 1 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0

для i = 1 (цикл) высоты из нолей -> 0 1 1 1 0 1, мы как бы отделяем i сверху строчек:
1 0 0 0 1 0 - 1ая строчка, тогда для каждого столбца в строчке считаем максимальную длину из 0 вверх(0 не должны
------------ прерываться 1, и эта последовательность должная начинаться в самой нижней строке, которую мы отделили.
0 0 0 0 1 0 Считаем гистограмму для этого ряда - ответ 3.
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0

для i = 2 (цикл) высоты из нолей -> 1 2 2 2 0 2, мы также отделяем i сверху строчек:
1 0 0 0 1 0 - 2 строчки.
0 0 0 0 1 0 Считаем гистограмму для этого ряда - ответ 6.
------------
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0

для i = 3 (цикл) высоты из нолей -> 2 3 0 3 1 3, мы также отделяем i сверху строчек:
1 0 0 0 1 0 - 3 строчки.
0 0 0 0 1 0 Считаем гистограмму для этого ряда - ответ 4.
0 0 1 0 0 0
------------
0 0 0 0 0 0
0 0 1 0 0 0

для i = 4 (цикл) высоты из нолей -> 3 4 1 4 2 4, мы также отделяем i сверху строчек:
1 0 0 0 1 0 - 4 строчки.
0 0 0 0 1 0 Считаем гистограмму для этого ряда - ответ 6.
0 0 1 0 0 0
0 0 0 0 0 0
------------
0 0 1 0 0 0

для i = 5 (цикл) высоты из нолей -> 4 5 0 5 3 5, мы также отделяем i сверху строчек:
1 0 0 0 1 0 - 5 строчки.
0 0 0 0 1 0 Считаем гистограмму для этого ряда - ответ 9.
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
------------

Вот и всё, теперь находим максимум среди всех полученных цифр(максимум не обязательно достигается на последнем шагу!!!)
max(3, 6, 4, 6, 9) = 9 - это и есть наш ответ.
0
Вездепух
Эксперт CЭксперт С++
12771 / 6653 / 1791
Регистрация: 18.10.2014
Сообщений: 16,817
20.07.2024, 19:04 3
Цитата Сообщение от n5 Посмотреть сообщение
Есть решение быстрее O(N), напиши саму идею.
Задача по определению не допускает решения быстрее чем за O(NM).

Обе задачи легко решаются достаточно наглядным алгоритмом:

0. Будем считать, что индексы в матрицах растут сверху-вниз, слева-направо
1. В дополнительной матрице S[N][M] будем хранить пары размеров [w, h] максимального прямоугольника с правым-нижним углом в этой точке
2. Для элемента S[i][j] результат можно получить на основе анализа и сравнения значений в S[i-1][j] и S[j][i-1].
3. Начальный значения для S[0][] или S[][0] (или обоих) назначаются тривиально.
0
Вездепух
Эксперт CЭксперт С++
12771 / 6653 / 1791
Регистрация: 18.10.2014
Сообщений: 16,817
21.07.2024, 08:05 4
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В дополнительной матрице S[N][M] будем хранить пары размеров [w, h] максимального прямоугольника с правым-нижним углом в этой точке
Хотя... похоже этого недостаточно. Все несколько сложнее...
0
447 / 315 / 62
Регистрация: 09.03.2016
Сообщений: 3,081
22.07.2024, 01:53 5
Ввод:
5 6
1 0 0 0 1 0
0 0 0 0 1 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
Если эту штуку распрямить, то получиться массив флагов.
Узнать, стоит ли над нулём ноль, можно отняв шесть по индексу.
Если под курсором ноль, (традиционное сканирование)
И отнять шесть тоже ноль, можно засчитывать как количество нулей прямоугольника.

Добавлено через 7 минут
Сложновато конечно. Не плюсы и не для начинающих.

Добавлено через 2 минуты
Здесь надо считать одновременно несколько прямоугольников.

Добавлено через 30 минут
Бывает массив счётчиков.
Ячейки инкреминируют.
Типа
C++
1
2
3
char counter[10]{};
   if(event)++counter[5];
if(event1)++counter[7];
Добавлено через 4 минуты
Шестизначный?
И привязать к столбам?
0
Эксперт С++
4121 / 1921 / 959
Регистрация: 01.06.2021
Сообщений: 6,773
Записей в блоге: 6
22.07.2024, 09:29 6
Наталья8, в инете полно решений данной задачи. Вот одна из них. Сложность O(n*m).

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
int maximalRectangle(vector<vector<char>>& matrix) {
    if (matrix.empty() || matrix[0].empty()) {
        return 0;
    }
 
    int m = matrix.size();
    int n = matrix[0].size();
    vector<int> left(n, 0);
    vector<int> right(n, n);
    vector<int> height(n, 0);
    int maxArea = 0;
 
    for (const auto& row : matrix) {
        int curLeft = 0, curRight = n;
 
        // Update height array
        for (int j = 0; j < n; j++) {
            if (row[j] == '1') {
                height[j]++;
            } else {
                height[j] = 0;
            }
        }
 
        // Update left boundary array
        for (int j = 0; j < n; j++) {
            if (row[j] == '1') {
                left[j] = max(left[j], curLeft);
            } else {
                left[j] = 0;
                curLeft = j + 1;
            }
        }
 
        // Update right boundary array
        for (int j = n - 1; j >= 0; j--) {
            if (row[j] == '1') {
                right[j] = min(right[j], curRight);
            } else {
                right[j] = n;
                curRight = j;
            }
        }
 
        // Calculate maximum area for each cell
        for (int j = 0; j < n; j++) {
            maxArea = max(maxArea, (right[j] - left[j]) * height[j]);
        }
    }
 
    return maxArea;
}
 
int main() {
    vector<vector<char>> matrix1 = {
        {'0', '1', '1', '0'},
        {'1', '1', '1', '1'},
        {'1', '1', '1', '1'},
        {'1', '1', '0', '0'}
    };
 
    cout << maximalRectangle(matrix1) << endl;
 
    return 0;
}
1
447 / 315 / 62
Регистрация: 09.03.2016
Сообщений: 3,081
23.07.2024, 01:30 7
Ты конечно очень шустрый такой молодой человек.
Только не работает этот мусор ни хрена.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// '1',
// '0',
int main() {
    vector<vector<char>> matrix1 = {
        {'1','0','0','0','1','0'},
        {'0','0','0','0','1','0'},
        {'0','0','1','0','0','0'},
        {'0','0','0','0','0','0'},
        {'0','0','1','0','0','0'}
    };
 
cout << maximalRectangle(matrix1) << endl;
    getchar();
    return 0;
}
Найти прямоугольную область белого цвета состоящую из наибольшего количества ячеек
0
447 / 315 / 62
Регистрация: 09.03.2016
Сообщений: 3,081
23.07.2024, 01:32 8
Согласен, может там условия были не такие,
или он вообще не из той оперы...
Я принципиально проверил.
0
Эксперт С++
4121 / 1921 / 959
Регистрация: 01.06.2021
Сообщений: 6,773
Записей в блоге: 6
23.07.2024, 02:23 9
Наталья8, выложенный мной код выводит площадь наибольшего черного прямоугольника (состоящего из единиц), а не белого (состоящего из 0). У ТС в условии сказано считать белые, поэтому там 9, а у тебя 2.
Неужели так сложно переделать код под условие?
0
863 / 513 / 215
Регистрация: 19.01.2019
Сообщений: 1,216
23.07.2024, 07:33 10
Цитата Сообщение от n5 Посмотреть сообщение
Эта задача сводится к задаче "Гистограмма".
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <cstdint>
#include <stack>
 
int main()
{
    size_t n, m, k;
    std::cin >> n >> m;
 
    uint64_t* h{ new uint64_t[m]{} }, s{};
    std::stack<std::pair<size_t, uint64_t>> st;
    auto maxS = [&](std::pair<size_t, uint64_t> h_) {
        while (!st.empty() && h_.second <= st.top().second) {
            k = st.top().first;
            s = std::max(s, (h_.first - k) * st.top().second);
            st.pop();
        }
        };
 
    for (size_t i{}; i != n; ++i) {
        for (size_t j{}, v; j != m; ++j) {
            std::cin >> v;
            h[j] = v ? 0 : h[j] + 1;
            k = j;
            maxS({ j, h[j] });
            if (h[j]) { st.push({ k, h[j] }); }
        }
        maxS({ m, 0 });
    }
    delete[] h;
 
    std::cout << "\n" << s;
 
}
0
447 / 315 / 62
Регистрация: 09.03.2016
Сообщений: 3,081
23.07.2024, 13:18 11
Цитата Сообщение от Royal_X Посмотреть сообщение
сложно переделать
Даа проблема.
0
Вездепух
Эксперт CЭксперт С++
12771 / 6653 / 1791
Регистрация: 18.10.2014
Сообщений: 16,817
31.07.2024, 08:11 12
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Хотя... похоже этого недостаточно. Все несколько сложнее...
Довел до некоего работоспособного варианта свой подход с анализом левого и верхнего соседа. В каждой клетке таблицы хранится набор прямоугольников-кандидатов на максимальность с правым-нижним углом в этой клетке.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <compare>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
 
struct Rect
{
  unsigned h, w;
 
  unsigned area() const
    { return h * w; }
 
  friend auto operator <=>(const Rect&, const Rect&) = default;
};
 
struct Corner
{
  unsigned limit_w, limit_h;
  std::set<Rect> rects;
};
 
using Mtr = std::vector<std::vector<unsigned char>>;
 
int main()
{
  unsigned n = 0, m = 0;
  std::cin >> n >> m;
 
  Mtr mtr(n + 1);
  for (auto& row : mtr)
    row.resize(m + 1);
 
  for (unsigned i = 1; i <= n; ++i)
  {
    for (unsigned j = 1; j <= m; ++j)
    {
      std::cin >> mtr[i][j];
      mtr[i][j] = mtr[i][j] == '0';
      std::cout << 1 - (unsigned) mtr[i][j] << ' ';
    }
    std::cout << std::endl;
  }
  std::cout << std::endl;
 
  Rect r_max = { 0, 0 };
  unsigned i_max = 0, j_max = 0;
 
  std::vector<Corner> rows[2];
  rows[0].resize(m + 1);
  rows[1].resize(m + 1);
 
  for (unsigned i = 1; i <= n; ++i)
    for (unsigned j = 1; j <= m; ++j)
    {
      rows[0][j] = std::move(rows[1][j]);
      rows[1][j] = {};
 
      if (!mtr[i][j])
        continue;
 
      rows[1][j].limit_h = rows[0][j].limit_h + 1;
      rows[1][j].limit_w = rows[1][j - 1].limit_w + 1;
 
      for (const Rect& r_l : rows[1][j - 1].rects)
        rows[1][j].rects.insert({ std::min(r_l.h, rows[1][j].limit_h), r_l.w + 1 });
 
      for (const Rect& r_u : rows[0][j].rects)
        rows[1][j].rects.insert({ r_u.h + 1, std::min(r_u.w, rows[1][j].limit_w) });
 
      if (rows[1][j].rects.empty())
        rows[1][j].rects.insert({ 1, 1 });
 
      for (const Rect& r : rows[1][j].rects)
        if (r.area() > r_max.area())
        {
          r_max = r;
          i_max = i;
          j_max = j;
        }
    }
 
  if (r_max.area() > 0)
  {
    for (unsigned i = 1; i <= n; ++i)
    {
      for (unsigned j = 1; j <= m; ++j)
        if (i > i_max - r_max.h && i <= i_max &&
            j > j_max - r_max.w && j <= j_max)
          std::cout << "* ";
        else
          std::cout << 1 - (unsigned) mtr[i][j] << ' ';
      std::cout << std::endl;
    }
    std::cout << std::endl;
  }
 
  std::cout << r_max.area() << std::endl;
}
Код
1 0 0 0 1 0
0 0 0 0 1 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0

1 0 0 0 1 0
0 0 0 0 1 0
0 0 1 * * *
0 0 0 * * *
0 0 1 * * *

9
0
Вездепух
Эксперт CЭксперт С++
12771 / 6653 / 1791
Регистрация: 18.10.2014
Сообщений: 16,817
01.08.2024, 07:32 13
Без лишнего вывода исходной матрицы:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <compare>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
 
struct Rect
{
  unsigned h, w;
 
  unsigned area() const
    { return h * w; }
 
  friend auto operator <=>(const Rect&, const Rect&) = default;
};
 
struct Corner
{
  unsigned limit_w, limit_h;
  std::set<Rect> rects;
};
 
using Mtr = std::vector<std::vector<unsigned char>>;
 
int main()
{
  unsigned n = 0, m = 0;
  std::cin >> n >> m;
 
  Mtr mtr(n + 1);
  for (auto& row : mtr)
    row.resize(m + 1);
 
  for (unsigned i = 1; i <= n; ++i)
  {
    for (unsigned j = 1; j <= m; ++j)
    {
      std::cin >> mtr[i][j];
      mtr[i][j] = mtr[i][j] == '0';
    }
  }
 
  Rect r_max = { 0, 0 };
  unsigned i_max = 0, j_max = 0;
 
  std::vector<Corner> rows[2];
  rows[0].resize(m + 1);
  rows[1].resize(m + 1);
 
  for (unsigned i = 1; i <= n; ++i)
    for (unsigned j = 1; j <= m; ++j)
    {
      rows[0][j] = std::move(rows[1][j]);
      rows[1][j] = {};
 
      if (!mtr[i][j])
        continue;
 
      rows[1][j].limit_h = rows[0][j].limit_h + 1;
      rows[1][j].limit_w = rows[1][j - 1].limit_w + 1;
 
      for (const Rect& r_l : rows[1][j - 1].rects)
        rows[1][j].rects.insert({ std::min(r_l.h, rows[1][j].limit_h), r_l.w + 1 });
 
      for (const Rect& r_u : rows[0][j].rects)
        rows[1][j].rects.insert({ r_u.h + 1, std::min(r_u.w, rows[1][j].limit_w) });
 
      if (rows[1][j].rects.empty())
        rows[1][j].rects.insert({ 1, 1 });
 
      for (const Rect& r : rows[1][j].rects)
        if (r.area() > r_max.area())
        {
          r_max = r;
          i_max = i;
          j_max = j;
        }
    }
 
  if (r_max.area() > 0)
  {
    for (unsigned i = 1; i <= n; ++i)
    {
      for (unsigned j = 1; j <= m; ++j)
        if (i > i_max - r_max.h && i <= i_max &&
            j > j_max - r_max.w && j <= j_max)
          std::cout << "* ";
        else
          std::cout << 1 - (unsigned) mtr[i][j] << ' ';
      std::cout << std::endl;
    }
    std::cout << std::endl;
  }
 
  std::cout << r_max.area() << std::endl;
}


https://coliru.stacked-crooked... 05a64ffd57
0
01.08.2024, 07:32
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.08.2024, 07:32
Помогаю со студенческими работами здесь

Прямоугольную матрицу A, состоящую из двух столбцов и N (вводится с клавиатуры) строк заполнить натуральными случайными
Прямоугольную матрицу A, состоящую из двух столбцов и N (вводится с клавиатуры) строк заполнить...

Найти вариант размещения на столе наибольшего количества костей
Имеются стол прямоугольной формы с размерами a×b (a и b – целые числа, a &gt; b) и кости домино с...

Шар белого цвета
В урне 3 белых, 2 черных и 1 синий шар. Из урны наудачу вынули один шар и вместо него положили...

Найти в предложении слово состоящее из наибольшего количества разных букв
Помогите пожалуйста, я в перл мягко говоря не очень найти в предложении слово состоящее из...

Найти в тексте первое слово состоящее из наибольшего количества цифр
Формулировка задачи:Найти в тексте первое слово - целое число, состоящее из наибольшего количества...

Найти в предложении слово, состоящее из наибольшего количества разных букв.
помогите решить. нужно к завтрешнему дню. оч надо(


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru