백준: Gold5③ - 1091, 1092, 1107
</br>
계속 계속
</br>
1091: 카드 섞기
https://www.acmicpc.net/problem/1091
플레이어 0, 1, 2에게 카드 정해서 주기
bool chk(){
for(int i = 0; i < d.size(); i++){
if( !(m[i%3].count(d[i])) ) return false;
}
return true;
}
// in main()
for(int i = 0; i < n; i++){
d[i] = i;
ori[i] = i;
}
int cnt = 0;
while( !chk() ){
if( ori == d && cnt ){
cout << -1 << endl;
return 0;
}
for(int i = 0; i < n; i++){
t[s[i]] = d[i];
}
d.swap(t);
cnt++;
}
cout << cnt << endl;
문제 이해가 좀 걸렸는데,
처음 카드: 0 1 2 3 4 5 6 7 8
P 순열 : 2 1 1 0 1 0 2 2 0
플레이어0: 3, 5, 8
플레이어1: 1, 2, 4
플레이어2: 0, 6, 7 을 받아야 함(주는 순서 상관x).
이런 뜻이었다.
for(int i = 0; i < n; i++){
int a;
cin >> a;
m[a].insert(make_pair(i, 1));
}
그래서 P를 입력 받을 때, map에 각 플레이어 마다 받아야 하는 카드들을 넣었다.
ori[]
에 처음의 카드 세팅, 즉 0, 1, 2, ..., n
을 저장해 둔다. 만약 카드를 계속 섞었는데 원본으로 돌아와 버리면, 평생 섞어도 목적을 못이루니 종료한다.
chk()
함수로 현재 덱으로 플레이어들에게 그대로 갈 수 있을 지 확인한다. 인덱스는 i%3
으로 0, 1, 2에 접근한다.
</br>
1092: 배
https://www.acmcpc.net/problem/1092
무게 제한이 있는 크레인들로 짐 옮기기
sort(c, c+n);
cin >> m;
for(int i = 0; i < m; i++){
int bx;
cin >> bx;
int j = 0;
for( ; j < n; j++){
if( bx <= c[j] ){
bxs[j]++;
break;
}
}
if( j == n ){
cout << -1 << endl;
return 0;
}
}
int sz = m, t = 0;
while( 1 ){
for(int i = n-1; i >= 0; i--){
for(int j = i; j >= 0; j--){
if( bxs[j] ){
bxs[j]--;
sz--;
break;
}
}
if( sz == 0 ) break;
}
t++;
if( sz == 0 ) break;
}
cout << t << endl;
크레인의 무게를 오름차순으로 정렬하고, bxs[]
에 해당 크레인이 옮길 수 있는 짐들의 수를 저장했다.
ex)
크레인: 1, 2, 4
짐 : 1, 1, 3, 3
bxs : 2, 0, 2
그 다음에, 무거운 걸 들 수 있는 크레인부터 무거운 짐을 옮겨 없앤다. 만약 한 바퀴 다 돌았다면 1분 지난 것이고, 짐을 다 옮기면 종료한다.
</br>
1107: 리모컨
https://www.acmcpc.net/problem/1107
리모컨 버튼이 몇 개 고장났을 때 최소로 버튼 눌러서 채널 옮기기
bool chk(int k){
if( k < 0 ) return false;
if( k == 0 && broken[k] ) return false;
while( k ){
if( broken[k%10] ) return false;
k /= 10;
}
return true;
}
// int main()
if( n == 100 ){
cout << 0 << endl;
return 0;
}
int ans = abs(n - 100);
if( chk(n) ) ans = min(ans, (int)(to_string(n).size()));
int cnt = 1;
while( n+cnt <= 1000001 || n-cnt >= 0 ){
if( chk(n-cnt) ){
cnt += to_string(n-cnt).size();
break;
}
if( chk(n+cnt) ){
cnt += to_string(n+cnt).size();
break;
}
cnt++;
}
cout << min(ans, cnt) << endl;
어떻게 할까 고민했는데
- 처음 100에서 움직이는 수
- 바로 그 채널로 움직일 수 있는 지 확인
- 목표 채널에서 +c, -c하며 가능한 지 확인(-c의 경우 +c보다 자리수가 적을 가능성이 있으므로 먼저 체크)
은근 음수 처리랑 고려할 게 많았다
</br>
현재 143문제를 풀고 학교 랭킹 130등이다
지금 탑 100에 들려면 190문제는 풀어야 한다 갈 길이 머네
</br>
댓글남기기