POJ 1088: Skiing

POJ 1088: Skiing

Original Problem Statement

Michael喜欢滑雪百这并不奇怪, 因为滑雪的确很刺激。可是为了获得速度,滑的区域必须向下倾斜,而且当你滑到坡底,你不得不再次走上坡或者等待升降机来载你。Michael想知道载一个区域中最长底滑坡。区域由一个二维数组给出。数组的每个数字代表点的高度。下面是一个例子
 1  2  3  4 5

16 17 18 19 6

15 24 25 20 7

14 23 22 21 8

13 12 11 10 9

一个人可以从某个点滑向上下左右相邻四个点之一,当且仅当高度减小。在上面的例子中,一条可滑行的滑坡为24-17-16-1。当然25-24-23-...-3-2-1更长。事实上,这是最长的一条。

Translation

On a 2D array, find the longest sequence of entries such that the sequence satisfies the following:
  • For every entry i in the sequence (excluding the last), the entry after it, j, is less than i.
  • For every entry i in the sequence (excluding the last), it is adjacent to the entry after it, j, on the 2D array.

How You Should Think Of This Problem

Find the longest decreasing subsequence in a 2D array.

How To Solve It

Instead of thinking how to implement LIS for a 2D array, think about how to convert it into a problem already seen before - well, 1D LIS.
Let's store the data in an 1D array and include its row and column to keep where the entry was from.

Then, to make sure requirement #1 is satisfied, we sort the array. The row and column data is still binded to the entries, however!
From here on, requirement #2 is easy to satisfy by checking every single entry pair.
This provides an O(n^4) algorithm, which runs in our time limits.

Code

Memoization (9/10)

#include <algorithm>
#include <iostream>
#include <cmath>
 
using namespace std;
 
int aray[105][105], b[105][105];
int r, c;
bool vist[105][105];
const int vx[] = {1, 0, -1, 0};
const int vy[] = {0, 1, 0, -1};
struct node
{
    int r, c;
};

int LIP(node x)
{
    if(b[x.r][x.c] != -1) return b[x.r][x.c];
    int maxi = 1;
    for(int d=0; d<4; d++)
    {
        int nr = x.r + vx[d];
        int nc = x.c + vy[d];
        if(nr >= 0 && nr < r && nc >= 0 && nc < c && \
           aray[x.r][x.c] > aray[nr][nc]) 
            maxi = max(maxi, LIP({nr, nc}) + 1);
    }
    return b[x.r][x.c] = maxi;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cin >> r >> c;
    for(int i=0; i<r; i++)
        for(int j=0; j<c; j++)
            cin >> aray[i][j];
    int best = 1;
    for(int sr=0; sr<r; sr++)
        for(int sc=0; sc<c; sc++)
        {
            for(int i=0; i<r; i++)
                for(int j=0; j<c; j++)
                    b[i][j] = -1;
            LIP({sr, sc});
            for(int qr=0; qr<r; qr++)
                for(int qc=0; qc<c; qc++)
                    best = max(best, b[qr][qc]);
        }
    cout << best << endl;
}

Tabulation (AC)

#include <algorithm>
#include <iostream>

using namespace std;

struct tile
{
    int h, x, y;
    constexpr bool operator<(const tile other) const
    {
        return h > other.h;
    }
} f[10005];
int b[10005];

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int r, c;
    cin >> r >> c;
    for(int i=0; i<r; i++)
        for(int j=0; j<c; j++)
        {
            cin >> f[i*c+j].h;
            f[i*c+j].x = i;
            f[i*c+j].y = j;
        }
    sort(f, f+r*c);
    int best = 0;
    for(int i=r*c-1; i>=0; i--)
    {
        for(int j=i+1; j<r*c; j++)
            if(abs(f[i].x - f[j].x) + abs(f[i].y - f[j].y) == 1 && f[i].h > f[j].h)
                b[i] = max(b[i], b[j] + 1);
        best = max(best, b[i]);
    }
    cout << best + 1 << endl;
}




Comments

Popular posts from this blog

OpenJudge 1768: Kadane's Algorithm on 2D Arrays

USACO 2018 Open: Milking Order and Topological Sort