문제

듣보잡 백준 1764번

리뷰

문제 이름이 특이해서 도전해봤다. ㅋㅋ

두개의 string 명단을 비교해서 중복되는 string들을 출력하는 프로그램을 만들어야 한다.

N개를 저장한 벡터를 만든 후, 입력받은 string을 찾으려고 했는데 시간초과 났다.

혼자 헤매다가 결국 질문 게시판을 찾아보니 정렬을 하세요 라는 글이 있었다.

정렬을 하면 같은 이름끼리 붙어있을테니까!! 덕분에 풀 수 있었다.

맞은 코드

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

int N, M, cnt; // 듣. 보
int max_len, min_len;
vector<string> v, answer;
string st;

int main(void){

    cin >> N >> M;

    for(int i = 0; i < N+M; i++){ // N+M개 모두 입력받기 
        cin >> st;
        v.push_back(st);
    }

    sort(v.begin(), v.end()); // 정렬 

     for(int i = 0; i < N+M-1; i++){
        if(v[i] == v[i+1]){   // 정렬하면 같은 단어는 붙어있다.  
            answer.push_back(v[i]);
            cnt++;
        }
    }

    cout << cnt << '\n';
    for(int i = 0; i < answer.size(); i++){
        cout << answer[i] << '\n';
    }
    return 0;
} 
728x90

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

이항계수1 백준 11050번 c++  (0) 2020.09.28
단어정렬 백준 1181번  (0) 2020.09.28
숨바꼭질6 백준 17087번 c++  (0) 2020.09.19
링크와 스타트 백준 15661번 c++  (0) 2020.09.17
8진수 2진수 백준 1212번  (0) 2020.09.16

문제

숨바꼭질6 백준 17087번

리뷰

수빈이의 위치와 1명 이상의 동생들의 위치가 주어진다.

수빈이가 어떤 간격 D로 움직여야 동생들을 전부 만날 수 있냐는 문제다.

수빈이의 위치와 동생들의 위치를 빼서 '거리'를 구한 배열을 만든다.

배열을 전부 순회하면서 '최대공약수'를 구한다.

int gcd(int a, int b){ //  유클리드 호제법으로 구하는 a, b의 최대공약수 
    if(b == 0) return a;
    else return gcd(b, a%b);
}  

동생이 1명이 올수도 있고, 2명일 수도 있으니까 동생 숫자를 유의해야 한다.

맞은 코드

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

int N, S, D; // 동생 수, 수빈 위치  
int A[100001]; // 동생들 위치  

int gcd(int a, int b){ // 최대공약수 

    if(b == 0) return a;
    else return gcd(b, a%b);
}  

int main(void){

    scanf("%d %d", &N, &S);

    for(int i = 0; i < N; i++){
        scanf("%d", &A[i]); // 동생의 위치 입력받음  
        A[i] = abs(A[i] - S); // 수빈의 위치와 동생의 위치의 '차이'로 갱신   
    }

    if(N == 1){ // 동생 수 N 1명  

        D = A[0];
    }else if(N == 2){ //동생 2명  

        D = gcd(A[0], A[1]); 
    }else{ 

        D = gcd(A[0], A[1]);

        for(int i = 2; i < N; i++){
            D = gcd(D, A[i]);
        }    
    }

    printf("%d", D);

    return 0;
}
728x90

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

단어정렬 백준 1181번  (0) 2020.09.28
듣보잡 백준 1764번 c++  (0) 2020.09.22
링크와 스타트 백준 15661번 c++  (0) 2020.09.17
8진수 2진수 백준 1212번  (0) 2020.09.16
2진수 8진수 백준 1373번  (0) 2020.09.15

문제

링크와 스타트 백준 15661번

리뷰

14889번 스타트와 링크 문제와 비슷했다.

스타트와 링크는 두 팀이 반드시 N/2 명씩 나뉘어야 했다.

이 문제는 두 팀이 1명 이상이면 된다는 조건이다. 하지만 팀 인원수가 1명이면, 능력치 계산을 못한다.

그래서 S팀이 2명일 때, S팀이 3명일 때, .... S팀이 N-2 명일 때의 경우를 모두 검사했다. DFS로 탐색했다.

    for(int i = 2; i < N-1; i++){  // 2명 부터 n-2명 까지의 범위 전부 검사 
        divideTeam(0, 0, i); 
    }

스타트와 링크 문제 풀이 포스팅

맞은 코드

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

int N;
int answer = 2e9;
bool check[21];
int S[21][21]; 

void countPower(){ // 팀별 능력치 비교  

    vector<int> Steam, Lteam; 
    int Spower=0, Lpower=0; 

    for(int i = 0; i < N; i++){  // 1. vector에 팀별 멤버번호 나눠담기 
        if(!check[i]) {
            Steam.push_back(i);
        }
        else Lteam.push_back(i);
    }    

    for(int i = 0; i < Steam.size(); i++){ // 2. 팀별 능력치 계산  
         for(int j = i+1; j < Steam.size(); j++){
             Spower = Spower + ( S[ Steam[i] ][ Steam[j] ] ) + ( S[ Steam[j] ][ Steam[i] ] );
        }
    }

    for(int i = 0; i < Lteam.size(); i++){  // Steam과 Lteam은 인원수가 다를 수 있다 
         for(int j = i+1; j < Lteam.size(); j++){
            Lpower = Lpower + ( S[ Lteam[i] ][ Lteam[j] ] ) + ( S[ Lteam[j] ][ Lteam[i] ] );
        }
    }

    // 3. 최소값 갱신 
    answer = min(abs(Spower-Lpower),  answer);

    return;
}

void divideTeam(int idx, int cnt, int target){ // N명중에 target 명 고르기  

    if(cnt == target) { // 팀 선택 완료 
        countPower();
        return;
    }

    for(int i = idx; i < N; i++){ // DFS로 완전탐색 

        if(check[i]) continue;

        check[i] = true;
        divideTeam(i+1, cnt+1, target);
        check[i] = false;
    }

}


int main(void){

     cin >> N;

     for(int i = 0; i < N; i++){
         for(int j = 0; j < N; j++){
             scanf("%d", &S[i][j]);
        }
    }

    for(int i = 2; i < N-1; i++){ // 2명 부터 n-2명 까지의 범위 전부 검사 
        divideTeam(0, 0, i); 
    }

    cout << answer;

    return 0;
} 
728x90

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

듣보잡 백준 1764번 c++  (0) 2020.09.22
숨바꼭질6 백준 17087번 c++  (0) 2020.09.19
8진수 2진수 백준 1212번  (0) 2020.09.16
2진수 8진수 백준 1373번  (0) 2020.09.15
진법변환 백준 2745번  (0) 2020.09.15

문제

8진수 2진수 백준 1212번


리뷰

8진수 한 자리는 2진수 세 자리로 표현할 수 있다.

예를 들어, 8진수 7은 2진수로 111 이다. 111은 곧 4+2+1 == 7 이기 때문이다.

8진수 1 자리가 들어왔을 때, 2진수 3자리로 바꿔서 스택에 넣어줬다.

가장 작은 자리수 부터 계산하니까. 스택에 넣은다음에 출력할 때는 올바른 순서로 나오기 때문에 스택을 선택했다.

8진수를 2로 나눈 나머지를 스택에 저장한다. 이 때, 나눗셈을 3번 한다.


처음에는 틀렸는데, 질문게시판을 보니까 0을 넣으면 0이 나와야 한다는 댓글을 봤다.

내코드에서는 0넣으면 아무것도 출력이 안됬었다.

이유는 스택에 001100 가 들어가 있다면, 1100 으로 출력하기 위해서였다. 0으로 시작하는 이진수는 없기 때문이다.

처음에는 스택의 top이 0이고, flag 가 false 라면 pop만 하고, 출력하지 않았다.

처음 1이 나올때 부터, flag를 true로 바꿔줘서, top 출력과 pop 둘 다 하도록 했다.

    bool flag= false;

    while(!answer.empty()){ // 스택 출력 

        if(answer.top() == 0 && flag == false){
            answer.pop();
            continue;
        }else{
            flag = true;
        }

        cout << answer.top();
        answer.pop();
    }

입력이 8진수 0이라면, 이진수도 답이 0이 나와야 하니까

while문의 첫번째 if문 조건을 수정했다.

    bool flag= false;

    while(!answer.empty()){ // 스택 출력 

        if(answer.top() == 0 && flag == false && answer.size() != 1){
            answer.pop();
            continue;
        }else{
            flag = true;
        }

        cout << answer.top();
        answer.pop();
    }

맞은 코드 1 (내가 짠 코드)

#include <iostream> 
#include <string>
#include <cstring> // strcpy()
#include <stack>
using namespace std;

string st;
char N[333335];
stack<int> answer;

int main(void){

     cin >> st;

     strcpy(N, st.c_str()); // string을 char 배열로 복사 

     int len = st.length(); // 8진수의 길이 

     for(int i = len-1; i >= 0 ; i--){

        int temp = N[i]-48;

        if(temp == 0){
            answer.push(0); answer.push(0); answer.push(0);
            continue;
        }

        for(int j = 0; j < 3; j++){ // 0이 아니라면,  2로 나눈 나머지를 stack에 push  
             answer.push(temp % 2);
             temp /= 2; 
        }
    }

    bool flag= false;

    while(!answer.empty()){ // 스택 출력 

        if(answer.top() == 0 && flag == false && answer.size() != 1){
            answer.pop();
            continue;
        }else{
            flag = true;
        }

        cout << answer.top();
        answer.pop();
    }

    return 0;
} 



내 코드가 어수선 하다는 느낌이 들었다. 다른 분들 코드를 찾아 보고 배웠다.

8진수를 2진수로 나타낼 수 있는 8가지 문자열을 미리 배열에 저장해두고 활용하는 방식이다.

first는 첫 숫자가 0이 나오면 안되니까 만들어 둔 배열이다. 0으로 시작하는 이진수는 없기 때문이다.

string first[8] = {"0", "1", "10", "11", "100", "101", "110", "111"};
string other[8] = {"000", "001", "010", "011", "100", "101", "110", "111"};

string st;
cin >> st;

cout << first[st[0] - '0'] ; // 문자로 된 숫자 하나에서 '0' 을 빼주면 숫자가 나온다  

first [ st[0] - '0' ] 이게 뭐지 싶었는데.

예를 들어, st[0] 이 문자 '3' 이라면, 문자 3에서 문자 0을 뺴야 숫자 3을 얻을 수 있다.

// st [0] == '3'

 first  [ '3' - '0' ] = first [3] 
 과 같다. 

 other[st[i] - '0']; 도 같은 구조다. 
 // st[0] 이 문자 5라면  (8진수로 5를 받았다면,) 
 other[ '5'-'0' ] == other [5] 가 된다. 이렇게 8진수를 2진수로 변환한다.  

가독성도 좋고 아주 배우고 싶은 코드여서 정리한다.


맞은 코드 2

#include <iostream> 
#include <string>
using namespace std;

string first[8] = {"0", "1", "10", "11", "100", "101", "110", "111"};
string other[8] = {"000", "001", "010", "011", "100", "101", "110", "111"};

int main(void){

    string st;
    cin >> st;

    cout << first[st[0] - '0'] ; // 문자로 된 숫자 하나에서 '0' 을 빼주면 숫자가 나온다  

    for(int i = 1; i < st.size(); i++){
        cout << other[st[i] - '0'];
    }

    return 0;
} 
728x90

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

숨바꼭질6 백준 17087번 c++  (0) 2020.09.19
링크와 스타트 백준 15661번 c++  (0) 2020.09.17
2진수 8진수 백준 1373번  (0) 2020.09.15
진법변환 백준 2745번  (0) 2020.09.15
진법변환2 백준 11005번 c++  (0) 2020.09.15

문제

2진수 8진수 백준 1373번


리뷰

2진수의 3 자리를 8진수의 1 자리로 만들 수 있다.

예를 들어 2진수 11001100 이 있다.

맨 오른쪽 부터 2의 0승, 2의 1승, 2의 2승이 곱해진 수다. ( 4, 2, 1)

3의 배수의 길이일때 이것이 성립한다.

11001100은 길이가 8이다. 8진수로 계산할 때는 11 001 100 으로 나눠질 수 있다.

첫번째 1과 두번째 1은 따로 처리해줘야 한다.

11 001 100 

11 을 8진수로 바꾼다. 
(2^1)x 1  + (2^0)x 1   // 2자리 일때는 2의 1승부터 시작!
    = 2 + 1 
    = 3 

001 을 8진수로 바꾼다. 
(2^2)x 0  + (2^1)x 0  +  (2^0)x 1   // 3자리 일때는 2의 2승부터 시작!
    = 0 + 0 + 1
    = 1    

100 을 8진수로 바꾼다. 
(2^2)x 1  + (2^1)x 0  +  (2^0)x 0 
    = 4 + 0 + 0
    = 4

이진수 문자열 길이가 4, 5, 6인 세 가지 경우가 있다.

이진수 문자열 길이가 4인 경우, (길이 % 3 == 1)

맨 앞의 수를 (2^0)x ? 으로 계산해주고,

나머지 3개의 수를 (2^2)x ? + (2^1)x ? + (2^0)x ? 식으로 계산하면 된다.


맞은 코드

#include <iostream> 
#include <cstring> //strlen() 
using namespace std;

char ch[1000001];

int main(void){

    scanf("%s", &ch); 

    int len = strlen(ch);

    if(len % 3 == 1){
        printf("%d", ch[0]-48 );

    }else if(len % 3 == 2){
        printf("%d",  2*( ch[0]-48 ) + ch[1]-48 );
    }    

    // 나머지 3의 배수로 떨어지는 길이만큼. len%3으로 시작해야 한다.
    for(int i = len%3; i < len; i += 3 ){
        printf("%d", 4 * ( ch[i]-48 ) +   2 * ( ch[i+1]-48 ) +  ch[i+2]-48 );
    }

    return 0;    
} 

728x90

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

링크와 스타트 백준 15661번 c++  (0) 2020.09.17
8진수 2진수 백준 1212번  (0) 2020.09.16
진법변환 백준 2745번  (0) 2020.09.15
진법변환2 백준 11005번 c++  (0) 2020.09.15
GCD합 백준 9613번  (0) 2020.09.15

문제

진법변환 백준 2745번


리뷰

B진법 수 N을 10진법으로 바꿔서 출력하는 프로그램 작성하기.

B진법은 2진법 부터 최대 36진법까지 입력된다.

N을 10진법으로 바꾸면 항상 10억보다 작거나 같다.


문자열로 N을 입력받고, 마지막 자리 문자 부터 B의 0승, B의 1승, B의 2승... 이렇게 곱해서 누적한 결과를 출력했다.

string 을 char 배열로 바꾸는 것은 cstring 의 strcpy 를 이용했다.

#include <cstring>
#include <string>

string N;
char ch[30];
strcpy(ch, N.c_str()); // string 을 char N에 복사  

*문자 '9'는 57에 대응하고 문자 'A'는 65 임을 이용했다. *

    if('9' < ch[i]){ // 알파벳으로 표현한 경우, A는 65임을 이용 
        answer = answer + ( pow(B, n) * (ch[i]-55) );
    }else{ // 문자 '9'는 57임을 이용 
            answer = answer + ( pow(B, n) * (ch[i]-48) );
    }

char 배열 길이 때문에 런타임 에러 발생

string 을 char 배열로 변환해서 쓰는 부분에서 런타임 에러를 이 글을 읽고 도움받았다.

예를 들어, 2진법이면 0과 1밖에 표현 안하니까 다른 진법에 비해 문자열이 길게 들어올 것이다.

N은 항상 10억보다 작거나 같다. 10억 ( 1,000,000,000)을 2진수으로 표현하면

0011 1011 1001 1010 1100 1010 0000 0000

따라서 char 배열은 30자리 이상으로 만드는 것이 안전하다.


맞은 코드

#include <iostream> 
#include <string>
#include <cstring> // strcpy()
#include <cmath> // pow()
using namespace std;

string N;
char ch[30];
int B, answer;

int main(void){

    cin >> N >> B;

    strcpy(ch, N.c_str()); // string 을 char N에 복사  
    int n = 0; // B의 자승 표현을 위한 변수 

    for(int i = N.length()-1; i >= 0; i--){

        if('9' < ch[i]){ // 알파벳으로 표현한 경우, A는 65임을 이용 
            answer = answer + ( pow(B, n) * (ch[i]-55) );
        }else{ // 문자 '9'는 57임을 이용 
            answer = answer + ( pow(B, n) * (ch[i]-48) );
        }
        n++;
    }

    cout << answer;

    return 0;    
} 

백준 질문게시판에 글 올려주시고 댓글 달아주시는 분들 모두 다 감사하다.

728x90

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

8진수 2진수 백준 1212번  (0) 2020.09.16
2진수 8진수 백준 1373번  (0) 2020.09.15
진법변환2 백준 11005번 c++  (0) 2020.09.15
GCD합 백준 9613번  (0) 2020.09.15
조합 0의 개수 백준 2004번  (0) 2020.09.15

문제

진법변환2 백준 11005번

리뷰

10진수 N을 B진수로 바꾸려면, N을 B로 나눈 나머지를 적어주다가 거꾸로 출력하면 된다.

계속 B로 나누는 것이다.

    while( N > 0){
        answer.push_back( N % B );
        N /= B; 
    }

문제의 조건에서 10 부터는 알파벳으로 표현하라고 했다.

그래서 10부터는 아스키코드를 이용해서 출력했다. 10일 때는 'A'를, 11 일 때는 'B' 로 출력해야 한다.

'A'는 65니까, 10 + 55 로 'A' 를 표현할 수 있다.

    for(int i = answer.size()-1; i >= 0 ; i--){ // 거꾸로 출력  

        if(answer[i] < 10){
            cout<< answer[i];
        }else{
            printf("%c", answer[i]+55);  // char 로 'A'는 10진수 65와 같다 
        }
    }

맞은 코드 1

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

int main(void){

      int N = 0, B = 0; 
    vector<int> answer; 

    cin >> N >> B;

    while( N > 0){
        answer.push_back( N % B );
        N /= B; 
    }

    for(int i = answer.size()-1; i >= 0 ; i--){ // 거꾸로 출력  

        if(answer[i] < 10){
            cout<< answer[i];
        }else{
            printf("%c", answer[i]+55);
        }
    }

    return 0;    
} 

stack을 이용한 다른 풀이

어차피 거꾸로 출력해야 하니까 '나머지 계산'한 것을 전부 스택에 push 하고,

스택일 빌 때까지 전부 pop 하면 된다.

알파벳을 출력하는 경우를 고려해서 char 를 저장하는 스택을 이용했다.

그런데 0부터 9까지는 어떻게 스택에 넣지? 싶어서 구글링 해보니까 4, 5 같은 숫자를 넣을때 앞에 문자로 '0'을 넣어준다.

맞은 코드 2

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

int main(void){

      int N = 0, B = 0; 

    cin >> N >> B;

    //printf("%d %d\n", '9', 'A'); // 57 65  7차이  
    stack<char> answer;

    while(N){

        int temp = N % B;

        if(temp >= 10){
            temp += 7;
        }

        answer.push('0'+temp);

        N /= B;
    }    

    while(!answer.empty()){
        cout << answer.top();
        answer.pop();
    }

    return 0;    
} 
728x90

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

2진수 8진수 백준 1373번  (0) 2020.09.15
진법변환 백준 2745번  (0) 2020.09.15
GCD합 백준 9613번  (0) 2020.09.15
조합 0의 개수 백준 2004번  (0) 2020.09.15
소인수분해 백준 11653번  (0) 2020.09.14

+ Recent posts