728x90

https://programmers.co.kr/learn/courses/30/lessons/42839

출처:프로그래머스

 

코딩테스트 연습 - 소수 찾기

한자리 숫자가 적힌 종이 조각이 흩어져있습니다. 흩어진 종이 조각을 붙여 소수를 몇 개 만들 수 있는지 알아내려 합니다. 각 종이 조각에 적힌 숫자가 적힌 문자열 numbers가 주어졌을 때, 종이

programmers.co.kr

 

#include <string>
#include <vector>
#include <cmath>
#include <set>
#include <iostream>
using namespace std;

set<int> numberSet;
//에라토스테네스의 체
bool isPrime(int n){
    if (n<2)
        return false;
    for (int i=2; i<=sqrt(n); i++){
        if (n%i == 0)
            return false;
    }
    return true;
}
//numbers로 숫자조합 만들기 -> numberSet 셋에 삽입
void makeCombination(string comb, string others){
    if (comb != "")
        numberSet.insert(stoi(comb)); //string to int
    
    for (int i=0; i<others.size(); i++)
        //재귀함수
        makeCombination(comb + others[i], others.substr(0,i) + others.substr(i+1));
}
int solution(string numbers) {
    int answer = 0;
    //numbers로 가능한 숫자 조합 만들기
    makeCombination("", numbers);

    set<int>::iterator iter;
    for(iter = numberSet.begin(); iter!=numberSet.end(); iter++){
        if(isPrime(*iter))
            answer++;
    }
    return answer;
}

 

python으로 준비하다가 c++하니까 너무 헷갈린다..ㅋㅋㅋㅋㅋ ㅠㅠ

728x90

https://programmers.co.kr/learn/courses/30/lessons/42840

출처: 프로그래머스

 

코딩테스트 연습 - 모의고사

수포자는 수학을 포기한 사람의 준말입니다. 수포자 삼인방은 모의고사에 수학 문제를 전부 찍으려 합니다. 수포자는 1번 문제부터 마지막 문제까지 다음과 같이 찍습니다. 1번 수포자가 찍는

programmers.co.kr

 

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

//수포자 3명 규칙
int p1[5] = {1,2,3,4,5};
int p2[8] = {2,1,2,3,2,4,2,5};
int p3[10] = {3,3,1,1,2,2,4,4,5,5};
    
vector<int> solution(vector<int> answers) {
    vector<int> answer;
    vector<int> score = {0,0,0};
    int max_score = 0;
    
    //완전 탐색
    for(int i=0; i<answers.size();i++){
        if (answers[i] == p1[i%5])
            score[0]++;
        if (answers[i] == p2[i%8])
            score[1]++;
        if (answers[i] == p3[i%10])
            score[2]++;
    }
    //max_score = max(max(score[0],score[1]), score[2]);
    max_score = *max_element(score.begin(), score.end());
    for(int i=0; i<score.size();i++){
        if (score[i] == max_score){
            answer.push_back(i+1);
        }
    }
    
    return answer;
}

 

728x90

문제

총 8개의 톱니를 가지고 있는 톱니바퀴 4개가 아래 그림과 같이 일렬로 놓여져 있다. 또, 톱니는 N극 또는 S극 중 하나를 나타내고 있다. 톱니바퀴에는 번호가 매겨져 있는데, 가장 왼쪽 톱니바퀴가 1번, 그 오른쪽은 2번, 그 오른쪽은 3번, 가장 오른쪽 톱니바퀴는 4번이다.

이때, 톱니바퀴를 총 K번 회전시키려고 한다. 톱니바퀴의 회전은 한 칸을 기준으로 한다. 회전은 시계 방향과 반시계 방향이 있고, 아래 그림과 같이 회전한다.

톱니바퀴를 회전시키려면, 회전시킬 톱니바퀴와 회전시킬 방향을 결정해야 한다. 톱니바퀴가 회전할 때, 서로 맞닿은 극에 따라서 옆에 있는 톱니바퀴를 회전시킬 수도 있고, 회전시키지 않을 수도 있다. 톱니바퀴 A를 회전할 때, 그 옆에 있는 톱니바퀴 B와 서로 맞닿은 톱니의 극이 다르다면, B는 A가 회전한 방향과 반대방향으로 회전하게 된다. 예를 들어, 아래와 같은 경우를 살펴보자.

두 톱니바퀴의 맞닿은 부분은 초록색 점선으로 묶여있는 부분이다. 여기서, 3번 톱니바퀴를 반시계 방향으로 회전했다면, 4번 톱니바퀴는 시계 방향으로 회전하게 된다. 2번 톱니바퀴는 맞닿은 부분이 S극으로 서로 같기 때문에, 회전하지 않게 되고, 1번 톱니바퀴는 2번이 회전하지 않았기 때문에, 회전하지 않게 된다. 따라서, 아래 그림과 같은 모양을 만들게 된다.

위와 같은 상태에서 1번 톱니바퀴를 시계 방향으로 회전시키면, 2번 톱니바퀴가 반시계 방향으로 회전하게 되고, 2번이 회전하기 때문에, 3번도 동시에 시계 방향으로 회전하게 된다. 4번은 3번이 회전하지만, 맞닿은 극이 같기 때문에 회전하지 않는다. 따라서, 아래와 같은 상태가 된다.

톱니바퀴의 초기 상태와 톱니바퀴를 회전시킨 방법이 주어졌을 때, 최종 톱니바퀴의 상태를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 1번 톱니바퀴의 상태, 둘째 줄에 2번 톱니바퀴의 상태, 셋째 줄에 3번 톱니바퀴의 상태, 넷째 줄에 4번 톱니바퀴의 상태가 주어진다. 상태는 8개의 정수로 이루어져 있고, 12시방향부터 시계방향 순서대로 주어진다. N극은 0, S극은 1로 나타나있다.

다섯째 줄에는 회전 횟수 K(1 ≤ K ≤ 100)가 주어진다. 다음 K개 줄에는 회전시킨 방법이 순서대로 주어진다. 각 방법은 두 개의 정수로 이루어져 있고, 첫 번째 정수는 회전시킨 톱니바퀴의 번호, 두 번째 정수는 방향이다. 방향이 1인 경우는 시계 방향이고, -1인 경우는 반시계 방향이다.

출력

총 K번 회전시킨 이후에 네 톱니바퀴의 점수의 합을 출력한다. 점수란 다음과 같이 계산한다.

  • 1번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 1점
  • 2번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 2점
  • 3번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 4점
  • 4번 톱니바퀴의 12시방향이 N극이면 0점, S극이면 8점

코드

# 14891
import sys
def rotate(gearnum, clockwise):
    isRotate = [False for _ in range(4)] # 각 톱니바퀴 회전 가능한지
    isDirection = [0 for _ in range(4)] # 각 톱니바퀴 방향
    isRotate[gearnum] = True
    isDirection[gearnum] = clockwise

    tempn = gearnum
    tempd = clockwise
    # gear[gearnum][6] 과 gearnum 전 톱니바퀴들의 [2]비교
    for i in range(gearnum-1,-1,-1):
        if gear[tempn][6] != gear[i][2]:
            # 다르면 반대방향으로 움직여야함
            tempd = -tempd # 새롭게 복사
            isDirection[i] = tempd
            tempn = i # 새롭게 복사
            isRotate[i] = True
        else: # 같으면 안움직여도됨
            break

    tempn = gearnum
    tempd = clockwise
    # gear[gearnum][2] 과 gearnum 후 톱니바퀴들의 [6]비교
    for i in range(gearnum+1, 4):
        if gear[tempn][2] != gear[i][6]:
            # 다르면 반대방향으로 움직여야함
            tempd = -tempd
            isDirection[i] = tempd
            tempn = i
            isRotate[i] = True
        else: # 같으면 안움직여도됨
            break

    # 톱니바퀴 회전
    for i in range(4):
        if isRotate[i]: # 회전 가능한 것만
            if isDirection[i] == 1: # 시계방향 회전
                # 마지막 pop해서 배열 처음에 붙이기
                tmp = gear[i].pop()
                gear[i] = [tmp] + gear[i]
            else: # 반시계방향 회전
                # 처음꺼 뽑아서 마지막에 붙이기
                tmp = gear[i][0]
                del gear[i][0]
                gear[i].append(tmp)

gear = []
for i in range(4):
    gear.append(list(sys.stdin.readline().rstrip()))
k = int(sys.stdin.readline()) #회전 횟수
for _ in range(k):
    # 톱니바퀴번호, 방향
    gear_num, clock_wise = map(int,sys.stdin.readline().split())
    rotate(gear_num-1, clock_wise)
result = 0
for i in range(4):
#     print(gear[i])
    if gear[i][0] == '1': # S극이면
        result += 2 ** i
print(result)

풀이

톱니바퀴가 맞물리는 상황에서 극이 같으면 안움직이고 다르면 반대방향으로 움직인다.

이를 봤을 때, 만약 2번톱니바퀴를 시계반대방향으로 움직이면

  1. gear[2][6] 과 gear[i][2]를 비교 (단, i 는 2번 톱니바퀴보다 작은 것들 중)
  2. gear[2][2] 과 gear[i][6]를 비교 (단, i 는 2번 톱니바퀴보다 큰 것들 중)

비교해서 같으면 break

다르면 회전할 수 있는지와 방향 표시

여기서 또 움직인 톱니바퀴 번호와 방향을 계속 기록해야 다음꺼에 영향을 줄 수 있다.

그래서 1 과 2 전에 tempn, tempd 변수에 기록해둔다.

 


회전

  • 시계방향 - 마지막 원소 뽑아서 맨 처음에 삽입
  • 반시계방향 - 처음 원소 뽑아서 맨 마지막에 삽입

 

728x90

문제

10진법 수 N이 주어진다. 이 수를 B진법으로 바꿔 출력하는 프로그램을 작성하시오.

10진법을 넘어가는 진법은 숫자로 표시할 수 없는 자리가 있다. 이런 경우에는 다음과 같이 알파벳 대문자를 사용한다.

A: 10, B: 11, ..., F: 15, ..., Y: 34, Z: 35

입력

첫째 줄에 N과 B가 주어진다. (2 ≤ B ≤ 36) N은 10억보다 작거나 같은 자연수이다.

출력

첫째 줄에 10진법 수 N을 B진법으로 출력한다.

코드

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

int main(){
    int n, b;
    cin >> n >> b;

    string b_num;
    while (n!=0){
        int tmp = n % b;
        if (tmp > 9){
            tmp = tmp - 10 + 'A';
            b_num += tmp;
        }
        else{
            b_num += ('0' + tmp);

        }
        n/=b;
    }
    reverse(b_num.begin(), b_num.end());
    cout << b_num << '\n';
    return 0;
}

풀이

이번주에 코테 잡힌게 python이 안되어서 망했다.

그래도 문법 기억해내면서 풀어보는중 ㅠㅠ

10미만까지는 그냥 수를 진법으로 나눈 자리 수를 리턴

10이상부터는 -10 하고 'A' 부터 시작..

최종적으로 거꾸로 출력해야한다.

728x90

p263

전보 문제

# 이코테 p262
# 전보
import sys
import heapq
INF = int(1e9)
n, m, c = map(int, sys.stdin.readline().split())
graph = [[] for i in range(n+1)]
for _ in range(m):
    x, y, z = map(int,sys.stdin.readline().split())
    graph[x].append((y,z))
distance = [INF] * (n+1)

def dijkstra(start):
    q = []
    # 시작 노드로 가기위한 최단 경로 0
    heapq.heappush(q, (0, start))
    distance[start] = 0
    while q:
        dist, now = heapq.heappop(q)
        if distance[now] < dist:
            continue
        for i in graph[now]:
            y, z = i[0], i[1] #y가 노드 z가 비용
            cost = dist + z
            if cost < distance[y]:
                distance[y] = cost
                heapq.heappush(q, (cost, y))
dijkstra(c)
cnt = 0
max_distance = 0
for d in distance:
    if d != INF:
        cnt += 1
        max_distance = max(max_distance, d)
print(cnt-1, max_distance)
728x90

문제

n(2 ≤ n ≤ 100)개의 도시가 있다. 그리고 한 도시에서 출발하여 다른 도시에 도착하는 m(1 ≤ m ≤ 100,000)개의 버스가 있다. 각 버스는 한 번 사용할 때 필요한 비용이 있다.

모든 도시의 쌍 (A, B)에 대해서 도시 A에서 B로 가는데 필요한 비용의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 도시의 개수 n이 주어지고 둘째 줄에는 버스의 개수 m이 주어진다. 그리고 셋째 줄부터 m+2줄까지 다음과 같은 버스의 정보가 주어진다. 먼저 처음에는 그 버스의 출발 도시의 번호가 주어진다. 버스의 정보는 버스의 시작 도시 a, 도착 도시 b, 한 번 타는데 필요한 비용 c로 이루어져 있다. 시작 도시와 도착 도시가 같은 경우는 없다. 비용은 100,000보다 작거나 같은 자연수이다.

시작 도시와 도착 도시를 연결하는 노선은 하나가 아닐 수 있다.

출력

n개의 줄을 출력해야 한다. i번째 줄에 출력하는 j번째 숫자는 도시 i에서 j로 가는데 필요한 최소 비용이다. 만약, i에서 j로 갈 수 없는 경우에는 그 자리에 0을 출력한다.

코드

# 11401
import sys
INF = int(1e9)
n = int(sys.stdin.readline()) # 도시 (노드)
m = int(sys.stdin.readline()) # 버스 (간선)
graph = [[INF]*(n+1) for _ in range(n+1)] # 최단경로 저장

# 자기 자신 지나는 경로 0으로 초기화
for a in range(1,n+1):
    for b in range(1,n+1):
        if a==b:
            graph[a][b] = 0

for _ in range(m):
    a, b, c = map(int,sys.stdin.readline().split())
    # 시작 도시와 도착 도시를 연결하는 노선은 하나가 아닐 수 있다.
    # graph[a][b] = c
    graph[a][b] = min(graph[a][b],c)

# 플로이드 워셜 수행
for k in range(1, n+1):
    for a in range(1, n+1):
        for b in range(1, n+1):
            graph[a][b] = min(graph[a][b], graph[a][k]+graph[k][b])

# 최단경로 출력
for a in range(1, n+1):
    for b in range(1, n+1):
        if graph[a][b] == INF: # 갈 수 없다면 0으로 출력
            print(0, end=" ")
        else:
            print(graph[a][b], end=" ")
    print()

풀이

시작 도시와 도착 도시를 연결하는 노선이 하나가 아닐 수 있다는 것에 주의해서

플로이드 워셜 알고리즘을 수행하면 된다.

728x90

문제

인체에 치명적인 바이러스를 연구하던 연구소에서 바이러스가 유출되었다. 다행히 바이러스는 아직 퍼지지 않았고, 바이러스의 확산을 막기 위해서 연구소에 벽을 세우려고 한다.

연구소는 크기가 N×M인 직사각형으로 나타낼 수 있으며, 직사각형은 1×1 크기의 정사각형으로 나누어져 있다. 연구소는 빈 칸, 벽으로 이루어져 있으며, 벽은 칸 하나를 가득 차지한다. 

일부 칸은 바이러스가 존재하며, 이 바이러스는 상하좌우로 인접한 빈 칸으로 모두 퍼져나갈 수 있다. 새로 세울 수 있는 벽의 개수는 3개이며, 꼭 3개를 세워야 한다.

예를 들어, 아래와 같이 연구소가 생긴 경우를 살펴보자.

2 0 0 0 1 1 0
0 0 1 0 1 2 0
0 1 1 0 1 0 0
0 1 0 0 0 0 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

이때, 0은 빈 칸, 1은 벽, 2는 바이러스가 있는 곳이다. 아무런 벽을 세우지 않는다면, 바이러스는 모든 빈 칸으로 퍼져나갈 수 있다.

2행 1열, 1행 2열, 4행 6열에 벽을 세운다면 지도의 모양은 아래와 같아지게 된다.

2 1 0 0 1 1 0
1 0 1 0 1 2 0
0 1 1 0 1 0 0
0 1 0 0 0 1 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

바이러스가 퍼진 뒤의 모습은 아래와 같아진다.

2 1 0 0 1 1 2
1 0 1 0 1 2 2
0 1 1 0 1 2 2
0 1 0 0 0 1 2
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 1 0 0 0 0 0

벽을 3개 세운 뒤, 바이러스가 퍼질 수 없는 곳을 안전 영역이라고 한다. 위의 지도에서 안전 영역의 크기는 27이다.

연구소의 지도가 주어졌을 때 얻을 수 있는 안전 영역 크기의 최댓값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 지도의 세로 크기 N과 가로 크기 M이 주어진다. (3 ≤ N, M ≤ 8)

둘째 줄부터 N개의 줄에 지도의 모양이 주어진다. 0은 빈 칸, 1은 벽, 2는 바이러스가 있는 위치이다. 2의 개수는 2보다 크거나 같고, 10보다 작거나 같은 자연수이다.

빈 칸의 개수는 3개 이상이다.

출력

첫째 줄에 얻을 수 있는 안전 영역의 최대 크기를 출력한다.

코드

# 14502
import sys
from collections import deque
import copy

def bfs():
    q = deque()
    tmp_graph = copy.deepcopy(graph) # 벽 설치 그래프 깊은 복사
    for i in range(N):
        for j in range(M):
            if tmp_graph[i][j] == 2: # 바이러스 있는 좌표만 큐에 넣기
                q.append((i,j))
    while q:
        x, y = q.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < N and 0 <= ny < M and tmp_graph[nx][ny] == 0:
                tmp_graph[nx][ny] = 2
                q.append((nx, ny))
    # 안전영역 ( 0인 칸 세기 )
    cnt0 = 0
    global answer
    for i in range(N):
        cnt0 += tmp_graph[i].count(0)
    answer = max(answer, cnt0)


def newwall(cnt):
    if cnt == 3:
        bfs() #벽 3개 새롭게 만들면 bfs 진행
        return #재귀함수로 돌아가서 벽 없애고 다시 재귀함수 
    for i in range(N):
        for j in range(M):
            if graph[i][j] == 0:
                graph[i][j] = 1 # 빈 칸이면 벽 설치
                newwall(cnt+1) # 벽 설치 재귀함수
                graph[i][j] = 0

N, M = map(int,sys.stdin.readline().split())
graph = [list(map(int,sys.stdin.readline().split())) for _ in range(N)]
dx = [0, -1, 0, 1]
dy = [-1, 0, 1, 0]
answer = 0
newwall(0) #벽 만들기
print(answer)

풀이

바이러스(2) 주변에서 빈칸(0) 중 3개를 선택해 벽(1)을 세우고 bfs로 바이러스가 퍼질 때, 0의 개수 중 최댓값을 구한다.

벽을 3개 세우는 모든 경우의 수에 bfs를 실행시켜 최대값을 구해야 한다.

이때, 경우의 수마다 bfs 실행 시, copy 라이브러리의 deepcopy를 사용한다.

+ Recent posts