문제

스택 수열 백준 1874번


리뷰

문제 맨 밑에 '힌트'를 읽고 이해 했다.

1부터 n 까지 수에 대해서는 반드시 push n번, pop n번이 수행되야 목표수열을 얻을 수 있다.

만약, 스택에 숫자가 남아있으면, 실패니까 "NO" 를 출력해야 한다.


1부터 n 까지 수를 차례로 push 한다.

for(i=1; i<=num; i++){ // 1 부터 n 까지 수는 반드시 들어온다. 

        st.push(i);
        answer.push_back('+');
}

그러나 pop을 하려면 스택의 top이 목표수열의 숫자와 일치하는지 계속 확인해줘야 한다. 그래서 while문으로 만들었다.


pop을 할 때는 목표 수열의 다음숫자를 타겟으로 해야하니까 목표수열의 인덱스도 증가시켜줘야 한다는게 중요하다.

스택이 비어있으면 pop도 불가하니까, empty() 함수로 스택이 비었는지 확인한다.

for(i=1; i<=num; i++){ // 1 부터 n 까지 수는 반드시 들어온다. 

        st.push(i);
        answer.push_back('+');

        while(!st.empty() && (st.top() == N[idx])){ // 수열의 숫자와 같으면, pop

            st.pop();
            answer.push_back('-');
            idx++; // 목표 수열의 인덱스도 증가시켜준다. 
        } 

}

예를 들어, 입력받은 수열크기는 8이다. 목표 수열은 4 3 6 8 7 5 2 1 이다.

목표 수열은 4 3 6 8 7 5 2 1 이다.  (현재는 idx = 0, N[idx] = 4 를 타겟으로 한다. )

1, 2, 3, 4 순으로 push 했다. (위의 코드로 보면 i가 4까지 진행된 상태다)

여기서 목표수열의 첫번째 숫자 4와 스택의 top 4 가 같아진다. 즉, while 문의 조건을 충족한다. 
pop 한다. 
목표수열의 다음 숫자 3 과 스택의 top 3이 또 같아진다.  
(idx = 1로 바뀌면서 N[idx] = 3 이 된다. )
pop 한다. 

다시 5, 6 순으로 push 한다. 
while 문의 조건을 다시 확인한다. 

**코드

#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;

int N[100001]; // 입력받은 수열  
vector<char> answer; // 출력할 +, - 담을 벡터  
stack<int> st;

int main(void){

    freopen("input.txt", "rt", stdin);

     int i, idx, num = 0;

     scanf("%d", &num); // num 이하의 수열을 입력받자. 

    for(i=0; i<num; i++){ // 목표 수열 입력받기 
        scanf("%d", &N[i]); 
    }  // 입력받기 끝  


    // answer에는 push 할 때 '+'를 넣고, pop 할 때 '-'를 넣는다.  

    for(i=1; i<=num; i++){ // 1 부터 n 까지 수는 반드시 들어온다. 

        st.push(i);
        answer.push_back('+');

        while(!st.empty() && (st.top() == N[idx])){ // 수열의 숫자와 같으면, pop

            st.pop();
            answer.push_back('-');
            idx++; // 목표 수열의 인덱스도 증가시켜준다. 
        } 

    }

    if(!st.empty()) printf("NO"); // 스택에 뭐가 남았다면 실패니까 "NO"
    else{
        for(i=0; i<answer.size(); i++){ // answer 에 담았던 문자들 순차출력 
            printf("%c\n", answer[i]);
        }   
    } 

     return 0;
}
728x90

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

ROT13 백준 11655  (0) 2020.08.27
에디터 백준 1406번 c++  (0) 2020.08.26
2007년 백준 1924번  (0) 2020.08.25
열 개씩 끊어 출력하기 백준 11721번  (0) 2020.08.25
그대로 출력하기 백준 11718번 c++  (0) 2020.08.24

문제

2007년 백준 1924번


리뷰

1년 전에 풀었던 건데, 다시 풀어봤다.

달 마다의 일 수는 M배열에 넣는다.

7로 나누었을 때 나머지로 요일을 구분해 출력할 문자열을 D배열에 넣어둔다.

입력이 3월 14일 이면, 14에 1월의 총 일수, 2월의 총 일수를 더한다. 3월은 안 더한다.

7로 나눈 나머지에 따라서 요일이 정해진다.


코드

#include <iostream>
using namespace std;

int main(void){

    int M[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
    string D[8] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};

    int A, B = 0;
    int day = 0;

    cin >> A >> B;

    day = B;

    for(int i = 1; i < A; i++){
        day += M[i];
    }

    cout << D[day % 7];

     return 0;
}
728x90

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

에디터 백준 1406번 c++  (0) 2020.08.26
스택 수열 백준 1874번  (0) 2020.08.26
열 개씩 끊어 출력하기 백준 11721번  (0) 2020.08.25
그대로 출력하기 백준 11718번 c++  (0) 2020.08.24
정수 삼각형 백준 1932  (0) 2020.08.22

문제

열 개씩 끊어 출력하기 백준 11721번


리뷰

인덱스가 10번째가 됬을 때 마다 개행문자를 출력하려고 했었는데, 잘 안됬다.

다른 분들 코드를 보면서 scanf 함수에서 특정 길이까지 읽어들일 수 있는 서식문자가 있다는 것을 알게됬다!


scanf 의 서식문자

scanf의 서식문자로는 c 문자, s 문자열, p 포인터, d 10진 정수 등 이 있다.

%와 서식문자는 반드시 명시해야 한다.

그리고 폭을 지정하거나 포인터의 형을 지정할 수 있는 등의 옵션이 있다.

#include <stdio.h>

int scanf(const char *format [,address ...]);
  • 폭 지정

    %와 서식 문자 사이에 정수값을 삽입하면, 입력값 중 읽어들일 최대 길이를 지정할 수 있다.

    scanf("%10s", &A);
  • 검색 문자 지정 (search_set)

    배열 주소에서, 특정 조건에 따라 읽어들이는 방법을 제공한다.

    [ ] 안에 쓴 문자들만 읽어들여 입력받는다. 즉, h, i, j, k 문자들만 입력받는다.

    이외의 문자들이 입력되면 입력을 중단한다.

    문자 맨 앞에 ^ 기호를 붙이면, x, y, z를 제외한 문자들만 입력받는다.

    char A[102];
    
    scanf("%[hijk]", A);
    
    scanf("%[^xyz]");

코드

#include <iostream>
using namespace std;

char A[102];

int main(void){

    while(scanf("%10s", &A) != EOF){
        printf("%s\n", A);
    }

    return 0;
}
728x90

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

스택 수열 백준 1874번  (0) 2020.08.26
2007년 백준 1924번  (0) 2020.08.25
그대로 출력하기 백준 11718번 c++  (0) 2020.08.24
정수 삼각형 백준 1932  (0) 2020.08.22
연속합2 백준 13398  (0) 2020.08.22

문제

그대로 출력하기 백준 11718번

리뷰

cin 은 공백을 만나는 순간까지만 입력을 받는다. 그래서 cin으로 풀 수는 없었고,

공백을 포함한 문자열이 100글자 이내인 조건을 읽고 char 배열을 만들어서 scanf로 풀었다.

다른 분들은 표준입력 stdin으로 fgets() 로 102글자 까지 입력받아서 풀었다.

/* fgets()
파일 입력 스트림에서 문자열을 가져와서 str이라는 주소에 넘겨준다. 

scanf()와는 달리, 개행문자를 만날 때 까지 문자열을 읽어들인다. 
마지막으로 읽은 문자 뒤에 자동적으로 NULL을 붙여서 반환한다. 

numChars : 입력받을 문자의 최대 개수
*/

char* fgets(char *str, int numChars, FILE *stream)

/*
성공적으로 읽어들이면, 함수는 str을 리턴한다. 
오류가 나도, EOF(파일의 끝)을 만나도 NULL이 리턴된다. 

참고로 scanf 함수는 개행 문자 뿐만이 아니라 ' ' 와 '\t' 에 의해서도 입력이 끝난다.

도움을 받은 BOJ 질문게시판의 필독 FAQ글
fgets 함수
scanf 함수

코드 1 : scanf 이용

#include <iostream>
using namespace std;

char A[102];

int main(void){

    while(scanf("%c", &A) != EOF){
        cout << A;
    }

    return 0;
}

**코드 2 : fgets이용

#include <iostream>
using namespace std;

char A[102];

int main(void){

    while(fgets(A, 102, stdin)){
        cout << A;
    }

    return 0;
}
728x90

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

2007년 백준 1924번  (0) 2020.08.25
열 개씩 끊어 출력하기 백준 11721번  (0) 2020.08.25
정수 삼각형 백준 1932  (0) 2020.08.22
연속합2 백준 13398  (0) 2020.08.22
연속합 백준 1912번  (0) 2020.08.19

문제

정수 삼각형 백준 1932번


리뷰

맨 위층부터 아래로 내려가면서 숫자의 합을 구하는데, 최대값을 출력하는 문제다.

선택한 수의 대각선 왼쪽 또는 대각선 오른쪽만 선택할 수 있다는 것이 핵심이다.


입력 배열을 A[n] [n] 으로 두고, 각 위치에서 숫자의 합 최대값을 배열 D[n] [n] 에 저장하는 DP로 풀었다.

삼각형 배열 A 의 인덱스를 표현하면 아래와 같다.

             (1, 1)

           (2, 1) (2, 2)

        (3, 1) (3, 2) (3, 3)

      (4, 1) (4, 2) (4, 3) (4, 4)

(1, 1) 은 1행 1열 을 뜻한다.

예를 들어, A[3] [2] 를 선택한 다음에는 A[4] [2] 또는 A[4] [3] 중에서만 선택 할 수 있다.

그런데 역으로 생각하면, A[4] [2] 는 D[3] [1] 위치에서 더한 최대합에서 오거나, D[3] [2] 위치까지 더한 최대합에서 이동 가능한 위치다.

그래서 D[4] [2] = A[4] [2] + max(D[3] [1] , D[3] [2] ) 가 된다.

왜냐하면 하나를 선택하면, 다음 행에서는 대각선 왼쪽 또는 대각선 오른쪽만 선택할 수 있기 때문이다.

도출된 점화식

D[i][j] = A[i][j] + max(D[i-1][j], D[i-1][j-1]);

모든 행의 1열과 마지막 열에는 위의 점화식으로는 처리하지 못하는 특징이 있다.

1열의 특징

(1, 1) ( 2, 1) (3, 1) 이처럼 1열에 위치한 것의 특징은 아래와 같다.

아래층으로 갈 때 마다 직전 행, 1열의 데이터가 그대로 온다.

예를 들어, (4, 2) 위치는 직전 행의 (3, 1) (3, 2) 둘 중에서 내려올 수 있는 위치다.

(4, 1)위치는 항상 (3, 1) 에서만 선택 당할 수 있다.

따라서 다음과 같은 점화식을 세울 수 있다.

D[i][j] = A[i][j] + D[i-1][j];

마지막열

마지막 열도 비슷하다.

(2, 2) (3, 3) (4, 4) 처럼 행과 열의 인덱스 슷자가 같은 경우를 말한다.

(4, 4)는 오직 (3, 3)에서만 선택 당할 수 있다.

따라서 다음과 같은 점화식을 세울 수 있다.

D[i][j] = A[i][j] + D[i-1][j-1];

A배열의 정수 범위는 (0~9999) 이고, D 배열이 누적합을 저장하기 때문에 D배열의 자료형은 long long 으로 해줘야 한다.


코드

#include <stdio.h>
#include <algorithm>
using namespace std;

int A[501][501];
long long D[501][501];

int main(void){

    int n = 0;
    int i, j, num, max_value = 0;

    scanf("%d", &n);
    for(i = 1; i <= n; i++){
        for(j = 1; j <= i; j++){
            scanf("%d", &num);
            A[i][j] = num;    
        }
    } // 입력받기 끝 

    D[1][1] = A[1][1];
    D[2][1] = D[1][1] + A[2][1];
    D[2][2] = D[1][1] + A[2][2];

     for(i = 3; i <= n; i++){

         for(j = 1; j <= i; j++){

              if(j == 1){ // 1열인 경우 
                  D[i][j] = A[i][j] + D[i-1][j];

             }else if(j == i){ // 마지막 열인 경우 
                  D[i][j] = A[i][j] + D[i-1][j-1];

             }else{
                 D[i][j] = A[i][j] + max(D[i-1][j], D[i-1][j-1]);
             }
        }      
    }    

    for(i = 1; i <= n; i++){ // 마지막 줄에서 최대값 찾기 
         if(max_value < D[n][i]){
             max_value = D[n][i];
        }     
    }

     printf("%lld", max_value);

    return 0;
}
728x90

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

열 개씩 끊어 출력하기 백준 11721번  (0) 2020.08.25
그대로 출력하기 백준 11718번 c++  (0) 2020.08.24
연속합2 백준 13398  (0) 2020.08.22
연속합 백준 1912번  (0) 2020.08.19
RGB거리 백준 1149  (0) 2020.08.19

문제

연속합2 백준 13398번


리뷰

연속합 문제를 풀고나서 2가 있길래 풀어봤는데, 어려웠다. 혼자서 2시간 매달려도 안되서 다른 분들의 풀이 포스팅을 읽어봤다.

주어진 수열 그대로인 경우, 수를 하나 제거하는 경우를 나눠서 2차원 배열로 관리하는 것이 핵심이었다.

처음에는 잘 이해가 안됬었다.


주어진 수열 그대로에서 연속합을 구하는 것은 D[n] [0]에서 한다.


코드

#include <stdio.h>
#include <algorithm>
using namespace std;

int N;
int A[100001];
int D[100001][2];
int max_value;

int main()
{
    int num, i = 0; 

    scanf("%d", &N);

    for(i = 1; i <= N; i++){
        scanf("%d", &num);
        A[i] = num;
    }

    D[1][0] = D[1][1] = A[1];

    max_value = max(D[1][0], D[1][1]);

    for (i = 2; i <= N; i++)
    {
        D[i][0] = A[i] +max(0, D[i-1][0]);
        D[i][1] = max(D[i-1][1] + A[i], D[i-1][0]);
        max_value = max( max(D[i][0], D[i][1]), max_value );
    }

    printf("%d", max_value);
}

참고한 포스팅

728x90

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

그대로 출력하기 백준 11718번 c++  (0) 2020.08.24
정수 삼각형 백준 1932  (0) 2020.08.22
연속합 백준 1912번  (0) 2020.08.19
RGB거리 백준 1149  (0) 2020.08.19
동물원 백준 1309  (0) 2020.08.18

문제

연속합 백준 1912번


리뷰

입력 수열을 저장하는 배열 A[] 와, i인덱스값을 마지막으로 했을 때의 최대값을 저장하는 D [] 배열이 필요하다.

예를 들어, A = [ 1, -2, 3] 이 주어진다면,

D[0] 에는 A[0]을 마지막으로 하는 수열의 최대값이 들어간다. D[0] = 1 이 된다.

D[1] 에는 A[1] 을 마지막으로 하는 수열의 최대값이 들어간다.

[1, -2] 의 합과 [-2] 의 합 중에서 큰 것을 저장한다.

D[1] = -1 이 된다.

여기서 [1, -2 ] 의 합을 구할 때, 앞서 구한 값 D[0] 이 수열에 포함되어 있다.

다시 표현하면, D[0] + A[1] 의 합과 A[1] 을 비교하는 것과 같다.


D[2] 에는 A[2] 를 마지막으로 하는 수열의 최대값이 들어간다.

[1, -2, 3] 의 합과 [-2, 3]의 합과 [3] 의 합중에서 큰 것을 저장한다.

여기서도 [1, -2, 3] 의 합을 구할 때, 앞서 구한 D[1]의 값이 수열에 포함되어 있다.

즉, D[1] + A[2] 의 합과 A[2] 를 비교하는 것과 같다.


점화식은 아래와 같다.

D[i] = max(D[i-1] + A[i], A[i]);

D[i] 를 구한 다음에, D[i] 중에서 최대값을 찾아야 한다.

max_value 변수를 따로 둬서 최대값을 갱신하면 답을 구할 수 있다.


코드

#include <stdio.h>
#include <algorithm>
using namespace std;

int A[100002];
int D[100002];

int main(void){

    int len, num = 0;
    int i = 0;
    long long max_value = 0;

    scanf("%d", &len);

    for(i = 1; i <= len; i++){ // 인덱스 1부터 시작 
        scanf("%d", &num);
        A[i] = num;
    }

    max_value = D[1] = A[1]; // 초기화 

    for(i = 2; i <= len; i++){

        D[i] = max(D[i-1] + A[i], A[i]);

        if(max_value < D[i]) max_value = D[i];

    }

    printf("%lld", max_value);

    return 0;
}
728x90

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

정수 삼각형 백준 1932  (0) 2020.08.22
연속합2 백준 13398  (0) 2020.08.22
RGB거리 백준 1149  (0) 2020.08.19
동물원 백준 1309  (0) 2020.08.18
1,2,3 더하기3 백준 15988  (0) 2020.08.17

+ Recent posts