본문 바로가기

PS - 알고리즘

2969 - 메뚜기

 

 

step 1

더보기

꽃잎이 많은 꽃은 절대 적은 꽃으로 이동할 수 없습니다. 그럼 꽃잎 수로 정렬을 한 다음 자기보다 더 많은 꽃만 고려해도 문제를 해결할 수 있습니다. 꽃잎 수로 정렬한 다음 문제를 해결합니다.

step 2

더보기

dp[i][j] : i,j에 있는 꽃에 있을 때 이동할 수 있는 최대 횟수

 

이 dp를 어떻게든 구하면 이 문제를 해결할 수 있습니다.

아래 그림에서 검은 칸에 메뚜기가 있다고 해봅시다. 이 칸에서의 dp값은 {빨간 칸에 있는 dp값의 최대값 + 1}입니다.

 

그럼 새로운 dp를 정의해 봅시다.

 

Ldp[i][j] : i,j 포함 자기 왼쪽에 있는 모든 dp값들의 최댓값

 

이 dp를 왼쪽, 오른쪽, 위쪽, 아래쪽 모두 만들면 이 문제를 해결할 수 있습니다. 이것은 펜윅트리로 만들 수 있습니다.

코드

더보기
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<string>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct data {
    int g,x, y;
    inline bool operator<(const data& temp)const {
        return g > temp.g;
    }
}b[2250001];
struct dp {
    int l, r, u, d;
}mapp[1501][1501];
int n;
struct dataa {
    int x, y, z;
}qu[2250001];
int find(int x, int y, int d) {
    int v = 0, p;
    if (d == 0) {
        p = y;
        while (p != 0) {
            v = max(v, mapp[x][p].l);
            p = p & (p - 1);
        }
        return v;
    }
    if (d == 2) {
        p = x;
        while (p != 0) {
            v = max(v, mapp[p][y].u);
            p = p & (p - 1);
        }
        return v;
    }
    if (d == 1) {
        p = n - y + 1;
        while (p != 0) {
            v = max(v, mapp[x][n - p + 1].r);
            p = p & (p - 1);
        }
        return v;
    }
    if (d == 3) {
        p = n - x + 1;
        while (p != 0) {
            v = max(v, mapp[n - p + 1][y].d);
            p = p & (p - 1);
        }
        return v;
    }
}
void update(int x, int y, int v) {
    int p;
    p = y;
    while (p <= n) {
        mapp[x][p].l = max(mapp[x][p].l, v);
        p = ((p | (p - 1)) + 1);
    }
    p = x;
    while (p <= n) {
        mapp[p][y].u = max(mapp[p][y].u, v);
        p = ((p | (p - 1)) + 1);
    }
    p = n - y + 1;
    while (p <= n) {
        mapp[x][n - p + 1].r = max(mapp[x][n - p + 1].r, v);
        p = ((p | (p - 1)) + 1);
    }
    p = n - x + 1;
    while (p <= n) {
        mapp[n - p + 1][y].d = max(mapp[n - p + 1][y].d, v);
        p = ((p | (p - 1)) + 1);
    }
}
int main() {
    int x, y, i,j,cnt=0,pos=1;
    scanf("%d%d%d", &n, &x, &y);
    for (i = 1;i <= n;i++) {
        for (j = 1;j <= n;j++) {
            cnt++;
            scanf("%d", &b[cnt].g);
            b[cnt].x = i;
            b[cnt].y = j;
        }
    }
    sort(b + 1, b + cnt + 1);
    for (i = 1;i <= cnt;i++) {
        int v = 0, sx = b[i].x, sy = b[i].y;
        if (sx > 1) {
            if (sy > 2) v = max(v, find(sx - 1, sy - 2, 0));
            if (sy < n-1) v = max(v, find(sx - 1, sy + 2, 1));
        }
        if (sx < n) {
            if (sy > 2) v = max(v, find(sx + 1, sy - 2, 0));
            if (sy < n - 1) v = max(v, find(sx + 1, sy + 2, 1));
        }
        if (sy > 1) {
            if (sx > 2) v = max(v, find(sx - 2, sy - 1, 2));
            if (sx < n - 1) v = max(v, find(sx + 2, sy - 1, 3));
        }
        if (sy < n) {
            if (sx > 2) v = max(v, find(sx - 2, sy + 1, 2));
            if (sx < n - 1) v = max(v, find(sx + 2, sy + 1, 3));
        }
        if (sx == x && sy == y) {
            printf("%d", v + 1);
            return 0;
        }
        qu[i].x = sx;
        qu[i].y = sy;
        qu[i].z = v+1;
        if (b[i].g != b[i + 1].g) {
            for (int j = pos;j <= i;j++) {
                update(qu[j].x, qu[j].y, qu[j].z);
            }
            pos = i + 1;
        }
    }
    return 0;
}

'PS - 알고리즘' 카테고리의 다른 글

1314 - 동굴 탐험  (0) 2024.09.16
31725 - 포닉스와 달구  (0) 2024.09.09
16324 - Jumbled String  (0) 2024.08.26
14207 - 약수 도로  (0) 2024.08.19
21034 - Go To Goal  (0) 2024.08.13