티스토리 뷰

요약

재귀 + dp

풀이과정

시간복잡도를 보기위해 최악의 경우를 본다면 숫자 2000, 질문 100만이며 0.5초를 요구한다.

숫자 2000 기준으로 본다면 O(n^2)는 가능한 범위에 들어온다.

즉 2중 반복문으로 모든 숫자에 대해 팰린드롬인지 아닌지를 확인하고 이를 저장한다면

이후 무슨 질문이 나오던지간에 O(1)으로 팰린드롬 여부를 확인할 수 있기 때문에 위배되지 않을 것이다.

 

모든 숫자의 조합에 접근하는 순간 O(n^2)를 충족하기 때문에

범위에 대한 펠린드롬 파악 방법은 무조건 O(1)이어야 함.

이는 팰린드롬의 특성을 고려하면 쉽게 해결가능하다.

 

일단 dp[n+1][n+1](1부터 시작하니까..)에 저장한다고 치고

 

질문에서 요구하는 답의 형식(1:팰린드롬임, 0:팰린드롬아님)으로 보면

숫자가 1개일때 -> 1 -> O(1)

숫자가 2개일때 -> 같으면 1, 다르면 0 -> O(1) 임은 쉽게 알 수 있다.

 

숫자가 3개이상일때부터는 같은 패턴을 보이는데,

                 

1. 빨간색끼리 같으면 1, 다르면 0 -> O(1)

2. 보라색 범위가 팰린드롬인가?

의 AND 조건이라는 점이다.

2번의 경우, 범위 크기를 1부터 늘리는 방향으로 진행해왔기 때문에 보라색 범위는 이미 전 단계에서 구해서 저장했다. 그 값을 가져오면 되니 O(1)이다.

 

문제는 모든 조건을 구할 때 범위가 좀 드럽다는 점인데...

대각선 방향 진행으로 우상단 방향 반복문을 진행해야 함

이는 한 대각선의 row, col값의 합이 같다는 점을 이용해 row, col을 관리하면 되지만...

 

나는 그냥 위의 패턴을 이용해 재귀로 풀었다.

왜냐면 질문에서 다 요구할지 안할지도 모름

표 다 채우려면 범위가 귀찮음

 

map[n+1][n+1]은 -1로 모두 초기화하였다. -1은 아직 기록되지 않았다는 뜻이다.

bool isF2(int a, int b)
{
    if(map[a][b] != -1)	//이미 저장된 여부가 있다면
        return map[a][b];
    if(a == b)	// 숫자 1개짜리 팰린드롬의 경우
        return map[a][b] = true;
    if(a > b)	// 짝수개일때 서로 크로스 되는 경우 예외처리
        return true;
    if(nums[a] != nums[b])	//본격적 검사 1 - 외곽 값이 서로 같은지
        return map[a][b] = false;
    
    return map[a][b] = isF2(a+1,b-1);	//본격적 검사 2 - 내부가 팰린드롬인지
}

메모이제이션 여부를 먼저 확인하고,

종료조건인 숫자 1개, 크로스 경우(이건 예외처리라 저장하지 않는다) 를 먼저 확인한다음

펠린드롬 여부를 검사한다. 검사 항목은 2가지이고 AND이기때문에 하나씩 조건검사해도 됨

코드

//https://www.acmicpc.net/problem/10942
using namespace std;
#include <iostream>
#include <vector>

vector<vector<int>> map;    //1 : 펠린드롬, 0: 펠린드롬 아님, -1: 아직 기록되지 않음
vector<int> nums;

bool isF2(int a, int b)
{
    if(map[a][b] != -1)
        return map[a][b];
    if(a == b)
        return map[a][b] = true;
    if(a > b)
        return true;
    if(nums[a] != nums[b])
        return map[a][b] = false;
    
    return map[a][b] = isF2(a+1,b-1);
}

int main()
{
    int N; scanf("%d", &N);
    map.resize(N+1,vector<int>(N+1,-1)); 
    nums.resize(N+1);
    for(int i = 1; i <= N; i++)
        scanf("%d", &nums[i]);
    int M;  scanf("%d", &M);
    while(M--)
    {
        int a, b;   scanf("%d %d",&a,&b);
        printf("%d\n",isF2(a,b));
    }
}

기억할 점

다른 사람의 풀이

 

'■ 알고리즘 > ◻ 백준' 카테고리의 다른 글

[C++]15486: 퇴사 2  (0) 2024.05.07
[C++]3111번: 검열  (0) 2024.05.05
[C++]4949번: 균형잡힌 세상  (0) 2023.03.05
[C++]1764번: 듣보잡  (0) 2023.03.05
[C++]1541번: 잃어버린 괄호  (0) 2023.02.26
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/10   »
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
글 보관함