인프런 커뮤니티 질문&답변

윽쓰욱스님의 프로필 이미지

작성한 질문수

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

4-A

4-A 오답 관련 질문입니다. (to_string 사용 시)

작성

·

148

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

 

안녕하세요. 강의 잘 듣고 있습니다!!

해당 문제를 푸는데, 이해가 되지 않는 현상이 있어 질문드려요

 

비트마스킹으로 조합을 획득하여 이를 다시 순번으로 복원하는 과정에서

ret += to_string(j+1); 로 하니 오답이 발생했습니다.
무엇이 문제일지 전혀 감을 못잡다가..,
ret += (char(j+1) +'0'); 으로 해주니 정답 처리가 되었는데요 그 이유가 무엇일지 궁금합니다.

감사합니다.

 

전체 코드 >>

#include <bits/stdc++.h>
using namespace std;

int N;
int mp, mf, ms, mv;

vector<vector<int>> m;

int main()
{

    cin >> N;
    cin >> mp >> mf >> ms >> mv;

    m = vector<vector<int>>(N, vector<int>(5, 0));

    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < 5; ++j)
        {
            cin >> m[i][j];
        }
    }

    /*
    0000000: 0
    0000001: 1
    0000010: 2
    0000011: 3
    ...
    */
    int min_C = 500 * 200;
    vector<string> ans;

    for (int i = 0; i < (1 << N); ++i)
    {

        int sum_p = 0, sum_f = 0, sum_s = 0, sum_v = 0, sum_c = 0;

        for (int j = 0; j < N; ++j)
        {
            // 비트 마스킹을 통한 조합 combination 획득
            if (i & (1 << j))
            {
                sum_p += m[j][0];
                sum_f += m[j][1];
                sum_s += m[j][2];
                sum_v += m[j][3];
                sum_c += m[j][4];
            }
        }

if (sum_p >= mp && sum_f >= mf && sum_s >= ms && sum_v >= mv)
{
    if (min_C > sum_c)
    {
        min_C = sum_c;
        string ret = "";
        for (int j = 0; j < N; ++j)
        {
            if (i & (1 << j))
            {
                // ret += to_string(j+1); << 오답
                ret += (char(j + 1) + '0'); // << 이렇게 해주니 비로소 정답
            }
        }
        ans = {ret};
    }
    else if (min_C == sum_c)
    {
        string ret = "";
        for (int j = 0; j < N; ++j)
        {
            if (i & (1 << j))
            {
                // ret += to_string(j+1); << 오답
                ret += (char(j + 1) + '0'); // << 이렇게 해주니 비로소 정답
            }
        }
        ans.push_back(ret);
    }
}
    }

    if (ans.empty())
        cout << -1;
    else
    {
        cout << min_C << "\n";
        sort(ans.begin(), ans.end());
        for (char s : ans[0])
        {
            cout << int(s - '0') << " ";
        }
    }
    return 0;
}

답변 1

0

큰돌님의 프로필 이미지
큰돌
지식공유자

안녕하세요 ㅎㅎ

두 부분의 코드를 찍어보시면 됩니다.

#include<bits/stdc++.h>
using namespace std; 

int main() {
    int j = 0;
    cout << to_string(j+1) << " : " <<  (char(j + 1) + '0'); 

    return 0;
}

왼쪽은 1, 오른쪽은 49를 출력하게 합니다.

49는 참고로 아스키코드로 1을 가리키는 문자입니다.

 


또 질문 있으시면 언제든지 질문 부탁드립니다.

좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)

감사합니다.

강사 큰돌 올림.


윽쓰욱스님의 프로필 이미지
윽쓰욱스
질문자

답변감사합니다.

 

강사님, 제가 질문드린 것은 댓글의 내용과는 조금 다른 것 같습니다.
강사님의 출력은 cout << string << " : " << asci ; 를 한 것이니,
왼쪽은 1, 오른쪽은 49 입니다.

제 질문은,

제 제출 코드를 보시면, ret += to_string(j+1) 을 통해 ret 에 char를 더해주고
최종 출력은 for(char s : ans[0]) cout << int(s-'0') << " " ; 을 통해 int 로 출력해주고 있습니다.

최종 출력은 to_string 을 이용한 방식이나 char(j+1)+'0' 이나 같습니다.
(프린트를 찍어보면)

허나, 답을 제출하면 to_string을 이용한 방식은 오답인것을 질문드려요!

큰돌님의 프로필 이미지
큰돌
지식공유자

안녕하세요 성욱님 ㅎㅎ

 

to_string 을 이용한 방식이나 char(j+1)+'0' 이나 같습니다.

>> 보통은 같습니다만 to_string이 좀 더 정확하다고 보시면 됩니다.

  • to_string(j+1) 은 정확한 문자열로 변환합니다. 예를 들어, j+1이 10일 경우 "10"으로 변환됩니다.

  • (char(j + 1) + '0')j+1의 결과를 ASCII 값으로 변환하여 해당하는 숫자 문자를 생성합니다. 이 방법은 j+1한 자리 숫자일 때만 정확하게 작동합니다.

 

그렇다면 차이는 어떻게 발생할까요?

바로 이 반례일 때 차이점이 발생합니다.

반례

14

100 100 100 100

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 2

50 50 50 50 1

50 50 50 50 1

 

이 경우에 답은 13 14를 출력해야 합니다.

ret += (char(j + 1) + '0')

이건 13 14를 출력하고

ret += to_string(j+1); 

이건 1 3 1 4 이렇게 출력을 하게 됩니다.

 

일단 성욱님이 짠 로직 자체는 1 3 1 4 이렇게 출력하는게 맞습니다.

제 생각에는 문자열을 쌓고 문자단위로 뽑아서 출력하는게 성욱님의 로직이니까요.

 

다만

ret += (char(j + 1) + '0')

이 코드는 왜 저 반례에서 13 14를 출력하게 될까요?

그부분은.

저 코드는 애초에 문자를 쌓을 때

: : 58 : 10
:> : 62 : 14
; : 59 : 11
;> : 62 : 14
< : 60 : 12
<> : 62 : 14
= : 61 : 13
=> : 62 : 14

이런식으로 아스키코드상 특수문자로 쌓아버리게 됩니다.

특수문자로 쌓기 때문에 = -> 숫자로 변환 -> 13 이렇게 되는 것이죠.

 

그러나 to_string 같은경우 올바르게

1014 : 62 : 14
11 : 59 : 11
1114 : 62 : 14
12 : 60 : 12
1214 : 62 : 14
13 : 61 : 13
1314 : 62 : 14

이렇게 쌓아버리기 때문에 13 -> 숫자로 변환 1, 3 -> 1 3 이렇게 출력이 되는 것이죠.

 

이런 차이가 있습니다. 🙂

 

디버깅 코드는 다음과 같습니다.

#include <bits/stdc++.h>
using namespace std;

int N;
int mp, mf, ms, mv;

vector<vector<int>> m;

int main()
{

    cin >> N;
    cin >> mp >> mf >> ms >> mv;

    m = vector<vector<int>>(N, vector<int>(5, 0));

    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < 5; ++j)
        {
            cin >> m[i][j];
        }
    }

    /*
    0000000: 0
    0000001: 1
    0000010: 2
    0000011: 3
    ...
    */
    int min_C = 500 * 200;
    vector<string> ans;

    for (int i = 0; i < (1 << N); ++i)
    {

        int sum_p = 0, sum_f = 0, sum_s = 0, sum_v = 0, sum_c = 0;

        for (int j = 0; j < N; ++j)
        {
            // 비트 마스킹을 통한 조합 combination 획득
            if (i & (1 << j))
            {
                sum_p += m[j][0];
                sum_f += m[j][1];
                sum_s += m[j][2];
                sum_v += m[j][3];
                sum_c += m[j][4];
            }
        }

if (sum_p >= mp && sum_f >= mf && sum_s >= ms && sum_v >= mv)
{
    if (min_C > sum_c)
    {
        min_C = sum_c;
        string ret = "";
        for (int j = 0; j < N; ++j)
        {
            if (i & (1 << j))
            {
                ret += to_string(j+1);  
                //ret += (char(j + 1) + '0'); // << 이렇게 해주니 비로소 정답
                cout << ret << " : " << (char(j + 1) + '0') << " : " << to_string(j+1) << '\n';
            }
        }
        ans = {ret};
    }
    else if (min_C == sum_c)
    {
        string ret = "";
        for (int j = 0; j < N; ++j)
        {
            if (i & (1 << j))
            { 
                ret += to_string(j+1);  
                //ret += (char(j + 1) + '0'); // << 이렇게 해주니 비로소 정답
                cout << ret << " : " << (char(j + 1) + '0') << " : " << to_string(j+1) << '\n';
            }
        }
        ans.push_back(ret);
    }
}
    }

    if (ans.empty())
        cout << -1;
    else
    {
        cout << min_C << "\n";
        sort(ans.begin(), ans.end());
        for (char s : ans[0])
        {
            cout << int(s - '0') << " ";
        }
    }
    return 0;
}




또 질문 있으시면 언제든지 질문 부탁드립니다.

좋은 수강평과 별점 5점은 제게 큰 힘이 됩니다. :)

감사합니다.

강사 큰돌 올림.