작성
·
149
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점은 제게 큰 힘이 됩니다. :)
감사합니다.
강사 큰돌 올림.
안녕하세요 성욱님 ㅎㅎ
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점은 제게 큰 힘이 됩니다. :)
감사합니다.
강사 큰돌 올림.
답변감사합니다.
강사님, 제가 질문드린 것은 댓글의 내용과는 조금 다른 것 같습니다.
강사님의 출력은 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을 이용한 방식은 오답인것을 질문드려요!