Миша і кукурудза#15

Миша і кукурудза (Розбір)

Аналіз алгоритму

Для зручності подальших обчислень перевернемо дошку знизу вгору. Клітинки по вертикалі та по горизонталі будемо нумерувати з . Тоді маршрут мишки буде пролягати з лівого верхнього кута – клітинка з координатами , у правий нижній – клітинку з координатами . А рух вниз по дошці буде кодуватися літерою F.

Зображення алгоритму

Нехай на плитці з координатами знаходиться зерняток. Нехай res[i][j] містить максимальну кількість зерняток, яку можна зібрати при русі з лівого верхнього кута в клітинку . Оскільки на плитку можна потрапити або з плитки (i - 1, j), або з (i, j - 1), то

res[i][j] = \max(res[i - 1][j], res[i][j - 1]) + a[i][j]

Можна також обійтися і без масиву res, здійснюючи обчислення в самому масиві а. Будемо проходити плитки підлоги (клітинки масиву) зверху вниз і зліва направо, поклавши

a[i][j] = \max(a[i - 1][j], a[i][j - 1]) + a[i][j]

Спочатку всі клітинки нульового рядка та нульового стовпця масиву а ініціалізуємо -1. Однак для коректного перерахунку значення слід обнулити одну з клітинок: або . У такому випадку нове значення клітинки стане рівним \max(a[0][1], a[1][0]) + a[1][1] = 0 + a[1][1] = a[1][1]. У подальшому всі значення будуть перераховані коректно.

Після проведених обчислень вже буде містити максимальну кількість зерняток, яку можна зібрати до досягнення плитки . Стан масиву а за підсумками обчислень:

Зображення масиву

Реалізація алгоритму

Вхідну інформацію про зернятка будемо зберігати в масиві a. Тобто на плитці з координатами знаходиться зерняток. Маршрут руху мишки будемо зберігати в масиві pos, що має довжину m + n - 1 ( і – розміри підлоги).

#define MAX 102
int a[MAX][MAX];
char pos[2*MAX];

Зчитуємо вхідні дані. Оскільки на плитках може знаходитися і 0 зерняток, то ініціалізуємо клітинки масиву числами -1. Дошку перевертаємо знизу вгору.

scanf("%d %d",&m,&n);
memset(a,-1,sizeof(a));
for(i = 1; i <= m; i++)
    for(j = 1; j <= n; j++)
        scanf("%d",&a[m-i+1][j]);

Перерахуємо клітинки масиву а так, щоб містило максимальну кількість зерняток, яку можна зібрати до досягнення плитки .

a[0][1] = 0;
for(i = 1; i <= m; i++)
    for(j = 1; j <= n; j++)
        a[i][j] = max(a[i-1][j],a[i][j-1]) + a[i][j];

Починаючи з плитки (i, j) = (m, n), рухаємося до плитки записуючи маршрут руху мишки в масиві pos. З плитки необхідно рухатися в (i - 1, j) або (i, j - 1), залежно від того, яке зі значень a[i - 1][j] або a[i][j - 1] більше.

i = m; j = n; ptr = 0;
while(i + j > 2)
{
    if (a[i-1][j] > a[i][j-1])
    {
        pos[ptr] = 'F';
        i--;
    }
    else
    {
        pos[ptr] = 'R';
        j--;
    }
    ptr++;
}

Виводимо маршрут руху мишки.

while(ptr--) printf("%c",pos[ptr]);
printf("\n");