13 / 13 / 9
Регистрация: 28.07.2017
Сообщений: 103
1

Задачу "Мышка и зернышки" решить с использованием динамической памяти

17.02.2018, 22:45. Показов 1300. Ответов 11

Author24 — интернет-сервис помощи студентам
Здравствуйте. Такая задача была уже описана ранее. Вот только хочу ее решить с использованием динамической памяти, поэтому использовался вектор.

Условие:
Кликните здесь для просмотра всего текста

В индийском храме пол прямоугольной формы выложен одинаковыми квадратными плитками 1 х 1, на каждую из которых высыпано от 0 до k зернышек (k ≤ 30000). Размеры пола m х n. Мышка выбегает из левого нижнего угла пола храма и двигается к входу в другую норку, расположенную в противоположном углу. Мышка может двигаться только вправо или вперед, собирая все зернышки с плитки, на которой она находится.

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

Входные данные:
Первая строка содержит числа m и n – размеры пола (1 ≤ m, n ≤ 100). Далее идет m строк, начиная сверху, в каждой из которых размещено n чисел – количество зернышек на соответствующей плитке.

Выходные данные:
Вывести маршрут движения мышки в формате: RRFFFRF (F – шаг вперед, R – шаг вправо).


Вот код:
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
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <iostream>
 
#define max(a, b) ((a > b) ? a : b)
 
main(void)
{
    //quantity of rows, quantity of columns
    short qRow, qCol;
    scanf ("%hd %hd", &qRow, &qCol);
    ++qCol;
 
    std::vector <std::vector <int> > mtx(qRow + 1);
    for (auto &vec : mtx)
    {
        vec.resize (qCol, 0);
    }
 
    //input values
    for (short i = 0; i < qRow; ++i)
    {
        for (short j = 1; j < qCol; ++j)
        {
            scanf ("%d", &mtx.at(i).at(j));
        }
    }
    //change the matrix
    for (short i = qRow - 1; i >= 0; --i)
    {
        for (short j = 1; j < qCol; ++j)
        {
            mtx.at(i).at(j) += max( mtx.at(i + 1).at(j), mtx.at(i).at(j - 1) );
        }
    }
 
    std::string str;
    //find the best path
    for (short row = 0, col = (qCol - 1); row < (qRow - 1) || col != 1; )
    {
        if (mtx.at(row).at(col - 1) > mtx.at(row + 1).at(col))
        {
            str += 'R';
            --col;
        }
        else
        {
            str += 'F';
            ++row;
        }
    }
    mtx.clear();
    reverse(str.begin(), str.end());
    //output into screen
    std::cout << str;
//    printf ("%s", str.c_str());
}
Результаты решения находятся тут. 2 теста валятся. Подскажите, пожалуйста, как можно оптимизировать код, используя динамическую память.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.02.2018, 22:45
Ответы с готовыми решениями:

Динамическое программирование: Мышка и зернышки
Задача с сайта e-olymp, номер 15: Мышка и зернышки В индийском храме пол прямоугольной формы...

Помогите пожалуйста решить задачу с динамической памятью и указателями
Тема: Структуры, указатели. Цель работы: научиться работать с указателями, описать структуру,...

зaдача с использованием динамической памяти
Дана квадратная матрица. Если суммы элементов строк матрицы различны, то транспонировать матрицу....

Решить задачу с использованием цикла While-until
Помогите сделать блок -схему, завтра экзамен а без нее нет допуска: 1. Программу реализовать в...

Решить задачу с использованием массивов
Детские пластиковые кубики трех цветов сложены в прямоугольный параллелепипед размером MxNxP...

11
1352 / 851 / 365
Регистрация: 26.02.2015
Сообщений: 3,799
17.02.2018, 22:51 2
Цитата Сообщение от dude78 Посмотреть сообщение
используя
Так используйте работу с динамической памятью, а не обёртку над ней.
0
13 / 13 / 9
Регистрация: 28.07.2017
Сообщений: 103
17.02.2018, 22:57  [ТС] 3
Цитата Сообщение от Nishen Посмотреть сообщение
обёртку
, скажите, пожалуйста, что такое обертка над динамической памятью?
0
1352 / 851 / 365
Регистрация: 26.02.2015
Сообщений: 3,799
17.02.2018, 22:59 4
Цитата Сообщение от dude78 Посмотреть сообщение
что такое обертка
Уровень абстракции.
0
13 / 13 / 9
Регистрация: 28.07.2017
Сообщений: 103
17.02.2018, 23:16  [ТС] 5
Nishen, т.е. vector использует обертку динамической памяти, а саму динамическую память использует массив созданный через new?
0
1352 / 851 / 365
Регистрация: 26.02.2015
Сообщений: 3,799
17.02.2018, 23:52 6
Ну, вы когда вектор используете, сами с памятью не работаете вручную. Вместо вас это делают методы класса vector, кем-то написанного для вас. Если речь идёт о работе с динамической памятью, надо с ней работать самому, я думаю: выделять необходимое количество самому и освобождать.
0
║XLR8║
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
18.02.2018, 02:27 7
Лучший ответ Сообщение было отмечено dude78 как решение

Решение

dude78, во первых: тебе динамаческая память в этой задаче как собаке 5я нога. Создал массив и радуешься, благо есть std::array

Цитата Сообщение от dude78 Посмотреть сообщение
std::vector <std::vector <int> > mtx(qRow + 1);
* * for (auto &vec : mtx)
* * {
* * * * vec.resize (qCol, 0);
* * }
Это делается в 1 строку

C++
1
std::vector<std::vector<int>> mtx(qRow + 1, std::vector<int>(qCol));
Цитата Сообщение от dude78 Посмотреть сообщение
mtx.at(i).at(j)
Вот да, начинай ошибки отлавливать без try { .. } catch(...) { ... } std::vector::at

Цитата Сообщение от dude78 Посмотреть сообщение
main(void)
Функция main должна возращать int.

Цитата Сообщение от dude78 Посмотреть сообщение
for (short i = 0; i < qRow; ++i)
Сейчас short это уже не всегда самый удобный тип данных для процессора, лучше int используй, а лучше беззнаковый unsigned

Цитата Сообщение от dude78 Посмотреть сообщение
#define max(a, b) ((a > b) ? a : b)
Зачем тебе макрос когда есть std::max из <algorithm>?

Цитата Сообщение от dude78 Посмотреть сообщение
str += 'R';
Писал бы сразу в выходной поток посимвольно. Ну или std::stringstream но я бы те 200 символов сразу написал бы в потом не парился, это не самое долгое что тут делается.

Цитата Сообщение от dude78 Посмотреть сообщение
reverse(str.begin(), str.end());
А реверс вообще лишний, кто сказал что надо вывод надо начинать с той точки откуда мышь начала двигаться?

Добавлено через 7 минут
Цитата Сообщение от dude78 Посмотреть сообщение
1 ≤ m, n ≤ 100
Массив 100 на 100... на 10 000 элементов тебе нужен вектор?

Цитата Сообщение от dude78 Посмотреть сообщение
std::cout << str;
Перевод строки не забывай добавлять в конце.

Добавлено через 1 час 43 минуты
dude78, Решил

Проверь работу на этих тестах:

Кликните здесь для просмотра всего текста

Код
$ ./test.sh 
Test: 1
2 3
3 2 4
1 5 1
Output:
RFR

Test: 2
5 1 
1
1
1
1
1
Output:
FFFF

Test: 3
4 4
0 1 1 1
0 0 0 0
0 0 2 0
1 0 0 0
Output:
FRRFFR

Test: 4
4 4
2 0 0 1
0 0 0 1
0 0 0 1
1 0 0 1
Output:
RRRFFF

Test: 5
2 2
0 0
0 0 
Output:
FR
Bash
1
2
3
4
5
6
7
8
#!/usr/bin/env bash
for test in [0-9]; do
    echo Test: $test
    cat $test
    echo Output:
    cat $test | ./run
    echo
done


Ну и если захочешь считерить смотри мое решение:

Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <array>
#include <string>
#include <algorithm>
 
int main()
{
    //quantity of rows, quantity of columns
    unsigned n, m;
    std::cin >> m >> n;
 
    std::array<std::array<std::pair<unsigned, char>, 102>, 102> a;
 
    //input values
    for (unsigned row = 0; row < m; ++row)
        for (unsigned col = 0; col < n; ++col)
            std::cin >> a[row][col].first;
 
    //change the matrix
    for (int row = m - 1; row > -1; --row)
        for (unsigned col = 0; col < n; ++col)
        {
            unsigned bottom = unsigned(row) == (m - 1) ? 0 : a[row + 1][col].first,
                     left = col ? a[row][col - 1].first : 0;
            a[row][col].first += std::max(left, bottom);
            if      (left > bottom) a[row][col].second = 'R';
            else if (left < bottom) a[row][col].second = 'F';
            else                    a[row][col].second = col > 0 ? 'R' : 'F';
        }
 
    //find the best path
    std::string path;
    for (int row = 0, col = n - 1; row < m && col > -1;)
    {
        path += a[row][col].second;
        a[row][col].second == 'R' ? --col : ++row;
    }
    std::cout << std::string(path.rbegin() + 1, path.rend()) << std::endl;
}
1
13 / 13 / 9
Регистрация: 28.07.2017
Сообщений: 103
18.02.2018, 03:19  [ТС] 8
outoftime, Спасибо . Валилось на тестах, когда на плитках лежало 0 зерен.

Вот код, который получился:

Кликните здесь для просмотра всего текста
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
#include <cstdio>
#include <vector>
#include <algorithm>
 
int main()
{
    //quantity of rows, quantity of columns
    int qRow, qCol;
    scanf ("%u %u", &qRow, &qCol);
 
    std::vector<std::vector<int>> mtx((qRow + 1), std::vector<int>(qCol + 1));
 
    //input values
    for (int i = 1; i < qRow + 1; ++i)
    {
        for (int j = 0; j < qCol; ++j)
        {
                scanf ("%d", &mtx.at(i).at(j));
        }
    }
 
    //change the matrix
    for (int i = 1; i <= qRow; ++i)
    {
        for (int j = qCol - 1; j >= 0; --j)
        {
            mtx.at(i).at(j) += std::max( mtx.at(i - 1).at(j), mtx.at(i).at(j + 1) );
        }
    }
 
    //find the best path
    int row = qRow, col = 0;
    for ( ;row > 1 && col < (qCol - 1); )
    {
        if (mtx.at(row).at(col + 1) > mtx.at(row - 1).at(col))
        {
            printf ("R");;
            ++col;
        }
        else
        {
            printf ("F");
            --row;
        }
    }
    
    //it's essential if there are 0-s at all cells
    while (row != 1)
    {
        printf ("F");
        --row;
    }
    while (col != qCol - 1)
    {
        printf ("R");
        ++col;
    }
 
    mtx.clear();
    printf ("\n");
    return 0;
}


И ссылка на результат.
0
║XLR8║
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
18.02.2018, 04:23 9
Цитата Сообщение от dude78 Посмотреть сообщение
Вот код, который получился:
Ох-ох-ох, почитай мой код, на досуге.... Не идеальный, но ИМХО покрасивше будет. Хотя это больше дело вкуса, наверное
0
13 / 13 / 9
Регистрация: 28.07.2017
Сообщений: 103
18.02.2018, 17:04  [ТС] 10
outoftime,
Цитата Сообщение от outoftime Посмотреть сообщение
начинай ошибки отлавливать
Как я поня, то проверка имеет такой вид:
C++
1
2
3
4
5
6
7
8
try
{
     scanf ("%d", &mtx.at(i).at(j));
}
catch (const std::out_of_range& e)
{
     printf ("Out of Range error.");
}
, а как проверить в условии оператора if?
Например,
C++
1
if (mtx.at(row).at(col + 1) > mtx.at(row - 1).at(col))
Будет так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
try
{
     if (mtx.at(row).at(col + 1) > mtx.at(row - 1).at(col))
     {
         printf ("R");;
         ++col;
     }
}
catch (const std::out_of_range& e)
{
     printf ("Out of Range error.");
}
0
║XLR8║
1212 / 909 / 270
Регистрация: 25.07.2009
Сообщений: 4,361
Записей в блоге: 5
18.02.2018, 19:26 11
dude78, да, но, одно БОЛЬШОЕ но: когда пипешь программу для ACM никто твой код смотреть не будет, пока ты в первый эшелонг не попадешь, но главное - скорость и тот факт что даже если ты отловишь выход за пределы массива тебе этот выход надо обрабатывать, и тут, опять, это всё дело ударяеет по скорость работы.

Если в двух словах: вызов std::vector::at бьет по производительности, и если у тебя четко заданы входные параметры и ты решаешь задачу на время тебе не надо никакие исключения, если они у тебя есть - что-то пошло не так. Вот почему я даже от вектора избавился в своем решении и использовал std::array, у него скорость работы как у обычных массивов и те пару килобайт которые я постоянно отжираю проходят условие задачи.

Представь у астронавта полетело ПО, собрали быстро команду из тех кого увидили и сказали вот входные данные, нужно чтобы выходные были вот такими чтобы ПО работало. Это задача на время с ограчениями по ресурсам и важно здесь всё. Я не скажу что это хороший подход или что такие ситуации бывают в реале. Просто лучше делать всё по максимуму быстрым без удара по чему либо, а потом, в каком-то месте вместо рукописного кода добавить STL который даст немного накладных расходов, которые по прежднему будут в пределах условия задачи, и сэкономят определенное время.

Меня понесло, будет вопрос - будет ответ.
1
13 / 13 / 9
Регистрация: 28.07.2017
Сообщений: 103
18.02.2018, 19:59  [ТС] 12
outoftime, Спасибо .
0
18.02.2018, 19:59
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.02.2018, 19:59
Помогаю со студенческими работами здесь

Решить задачу с использованием рекурсии
Функция f(n) определена для целых положительных чисел следующим образом: f(n)=1, если n=1 или...

Решить задачу с использованием процедуры.
n Разработать подпрограмму вычисления S= ∑ 1/k^2. С использованием этой подпрограммы получить ...

Решить задачу с использованием функции.
n Разработать подпрограмму вычисления S= ∑ 1/k^2. С использованием этой подпрограммы получить ...

Симметричность массива с использованием динамической памяти
Дан массив, заполненный случайными числами. Определить, является ли он симметричным, т.е. одинаково...

Написать программу с использованием динамической памяти
Все данные должны вводиться с клавиатуры. Нужно так же использовать динамическую память Разбить...


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

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