2606번: 바이러스

첫째 줄에는 컴퓨터의 수가 주어진다. 컴퓨터의 수는 100 이하이고 각 컴퓨터에는 1번 부터 차례대로 번호가 매겨진다. 둘째 줄에는 네트워크 상에서 직접 연결되어 있는 컴퓨터 쌍의 수가 주어��

www.acmicpc.net

 

<내 코드>

 

N = int(input())
P = int(input())
# 인덱스 번호 맞추기 위해 한 줄 추가
graph = [[0]*(N+1) for _ in range(N+1)]
done = []

for _ in range(P):
    x, y = map(int, input().split())
    graph[x][y], graph[y][x] = 1, 1


def dfs(v):
    done.append(v)
    for k in range(1, N+1):  # 1 ~ n번까지
        if (k not in done) and (graph[v][k] == 1):
            dfs(k)

    return (len(done) - 1)  # 1번을 제외한 컴퓨터 수


print(dfs(1))

 

문제 자체는 DFS를 구현한다면 어렵지 않았다. 아직은 DFS를 자유롭게 구현하는게 힘들다...이 문제에서 인접행렬 방식을 이용해 DFS를 구현했다.

반응형

 

 

2178번: 미로 탐색

첫째 줄에 두 정수 N, M(2 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 M개의 정수로 미로가 주어진다. 각각의 수들은 붙어서 입력으로 주어진다.

www.acmicpc.net

 

<내 코드>

 

N, M = map(int, input().split())
maze = [list(input()) for _ in range(N)]  # List[str]
# 방문 경로
done = [[0]*M for _ in range(N)]

# 좌,우,상,하 탐색을 위한 설정
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]

# BFS 그래프 탐색
def bfs(x, y):

    done[0][0] = 1  # 시작점
    queue = [(0, 0)]  # 큐 사용

    while queue:
        now = queue.pop(0)
        for i in range(4):
            nx = now[0] + dx[i]
            ny = now[1] + dy[i]

            if (0 <= nx < N) and (0 <= ny < M):
                if done[nx][ny] == 0 and maze[nx][ny] == '1':
                    done[nx][ny] = done[now[0]][now[1]] + 1
                    queue.append((nx, ny))
    return done[-1][-1]

print(bfs(0, 0))

처음 풀어보는 BFS 문제였는데.. 이해하는데 꽤나 어려웠다. 계속 반복적으로 생각하고 익혀야겠다.

 

1. 방문한 경로를 저장하기 위해 done 배열을 만든다.

2. 길을 찾아나갈 노드를 queue에 담아준다.

3. 좌표가 경로를 벗어나지 않는다면 '방문 여부 확인', '길이 맞는지' 확인한다.

4. 상,하,좌,우로 확인해 연결된 좌표를 확인한다.

5. 조건에 맞다면 방문 여부 수정 후, 큐에 넣어 다음 차례에 추가한다.

6. 방문여부 수정 때, 몇 번째 방문인지 현재 좌표의 방문 값에 +1을 더해준다.

7. done 배열의 가장 마지막 요소를 출력하면 몇 번째만에 도착인지 알 수 있다.

반응형

 

 

1783번: 병든 나이트

첫째 줄에 체스판의 세로 길이 N와 가로 길이 M이 주어진다. N과 M은 2,000,000,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

<내 코드>

 

N, M = map(int, input().split())
cnt_block = 1


if N == 1:
    cnt_block = 1
elif N == 2:
    if (M >= 7):
        cnt_block = 4
    else:
        cnt_block = (M+1) // 2

elif N >= 3:
    if(M >= 7):
        cnt_block = (M - 2)
    elif(M >= 4):
        cnt_block = 4
    else:
        cnt_block = M

print(cnt_block)

 

경우 별로 따져줘야 할 조건이 까다로웠다... 문제 자체는 어렵지 않으나 경우 별로 조건을 잘 못하면 머리가 복잡해지는 문제다..

반응형

 

 

2217번: 로프

N(1≤N≤100,000)개의 로프가 있다. 이 로프를 이용하여 이런 저런 물체를 들어올릴 수 있다. 각각의 로프는 그 굵기나 길이가 다르기 때문에 들 수 있는 물체의 중량이 서로 다를 수도 있다. 하지만

www.acmicpc.net

 

 

<내 코드>

 

N = int(input())

weights = [int(input()) for _ in range(N)]
weights.sort(reverse=True)  # 내림차순


for i in range(N):
    weights[i] = weights[i] * (i+1)

print(max(weights))

 

 

문제 접근 방법

- 로프를 병렬로 연결하면 각 로프에는 w/k만큼의 동일한 중량이 걸린다.

- 즉, 가장 작은 무게를 들 수 있는 로프가 들 수 있는 질량 * 병렬연결 로프 개수 = 최종 무게

- 가장 무거운 무게를 들 수 있는 로프부터 내림차순으로 정렬한다.

 

처음에는 너무 어렵게 접근해서 복잡하게 생각했다. 그래서 디큐를 활용해 하나씩 빼고 넣고 하려고 했다가 실패했다. 이렇게 단순하게 풀릴지는... 후..

반응형

1. 라우팅 테스트

const express = require('express');
const jwt = require('jsonwebtoken');

const app = express();

app.get('/api', (req, res) => {
  res.json({
    message: 'Welcome to the API'
  });
});



app.listen(5000, () => console.log('Server started on port 5000'));

- express: 프로젝트에서 사용할 웹서버 프레임워크

- jsonwebtoken: 이 예제프로젝트에서 사용되는 핵심 모듈이다. JSON Web Token을 손쉽게 생성하고, 또 검증도 해준다.

 

'/api' URL로 get 요청을 하면 성공적으로 메시지가 나오게 된다.

 

 

 

2. 사용자 정보 암호화 토큰 생성

app.post('/api/login', (req, res) => {
  // Mock user
  const user = {
    id: 1,
    username: 'brad',
    email: 'bread@gmail.com'
  }

# 사용자 정보 암호화 - sign(전달할 내용, 비밀 키, 유효시간, 콜백)
  jwt.sign({ user }, 'secretkey', { expiresIn: '30s' }, (err, token) => {
    res.json({
      token
    });
  });
});

 

jwt.sign(payload, secretOrPrivateKey, [options, callback])

- payload : 객체 리터럴, 버퍼 또는 유효한 JSON을 나타내는 문자열. 여기선 임시 유저 정보를 넣어줬다.

- 두 번째 인자 : 비밀 키 전달

- 세 번째 인자 : 토큰에 대한 정보를 객체로 전달

- 네 번째 인자 : 콜백함수 작성. 만약 콜백 함수를 작성하지 않으면 동기 처리가 된다.

 

 

 

3. 토큰 해싱 작업 

app.post('/api/posts', verifyToken, (req, res) => {
# 암호 토큰 해싱작업
  jwt.verify(req.token, 'secretkey', (err, authData) => {
    if (err) {
      res.sendStatus(403);
    } else {
      res.json({
        message: 'Post created...',
        authData
      });
    }
  });
});

function verifyToken(req, res, next) {
  // Get auth header value
  const bearerHeader = req.headers['authorization'];
  // Check if bearer is undefined
  if (typeof bearerHeader !== 'undefined') {
    // Split at the space
    const bearer = bearerHeader.split(' ');
    // Get token from array
    const bearerToken = bearer[1]; // 토큰 값
    // Set the token
    req.token = bearerToken;
    // Next middleware
    next();

  } else {
    // Forbidden
    res.sendStatus(403);
  }
}

 

jwt.verify(token, secretOrPublicKey, [options, callback]) 

: jsonwebtoken 모듈에서 권한을 확인하는 메서드

 

- 첫 번째 인자 : 토큰 값을 전달

  • 인증이 된 유효한 토큰인지 확인하기 위한 것

  • 토큰은 쿠키에 저장되어 있으므로 요청 객체에서 cookies 속성을 확인하면 된다. ( express에서는 자동으로 cookieparser 미들웨어가 등록되어 있다. )

- 두 번째 인자 : 토큰 생성 시에 사용한 비밀 키를 디코딩하기 위해 똑같이 사용한다.

- 네 번째 인자 : 콜백함수 유무에 따라 비동기, 동기로 동작한다. 

 

위의 코드에서 로그인한 사용자는 JWT토큰을 생성받았기에 어떤 API를 사용할 권리가 있게 된다.

/api/posts URL로 요청하면, 쿠키에서 토큰 값을 읽고 verify() 함수를 호출해 json객체를 반환한다.

 

 

 

<전체 코드>

 

const express = require('express');
const jwt = require('jsonwebtoken');


const app = express();

app.get('/api', (req, res) => {
  res.json({
    mesaage: 'Welcom to the API'
  });
});

app.post('/api/posts', verifyToken, (req, res) => {
  jwt.verify(req.token, 'secretkey', (err, authData) => {
    if (err) {
      res.sendStatus(403);
    } else {
      res.json({
        mesaage: 'Post Created..',
        authData
      });
    }
  });

});

app.post('/api/login', (req, res) => {
  // Mock user
  const user = {
    id: 1,
    username: 'brad',
    email: 'brad@gmail.com'
  }

  jwt.sign({ user: user }, 'secretkey', { expiresIn: '30s' }, (err, token) => {
    res.json({
      token // token: token
    });
  });
});

// FORMAT OF TOKEN
// Authorization: Bearer <access_token>

// Verify Token
function verifyToken(req, res, next) {
  // Get auth header value
  const bearerHeader = req.headers['authorization'];
  // Check if bearer is undefined
  if (typeof bearerHeader !== 'undefined') {
    // Split at the space
    const bearer = bearerHeader.split(' ');
    // Get token from array
    const bearerToken = bearer[1];
    // Set the token
    req.token = bearerToken;
    // Next middlewear
    next();
  } else {
    // Forbidden
    res.sendStatus(403);
  }
}

app.listen(5001, () => console.log('Server started on port 5001'));
반응형

 

 

10162번: 전자레인지

3개의 시간조절용 버튼 A B C가 달린 전자레인지가 있다. 각 버튼마다 일정한 시간이 지정되어 있어 해당 버튼을 한번 누를 때마다 그 시간이 동작시간에 더해진다. 버튼 A, B, C에 지정된 시간은 ��

www.acmicpc.net

 

<내 코드>

 

T = int(input())

A, B, C = 0, 0, 0

while T > 0:
    if T >= 300:
        A = (T // 300)
        T = (T % 300)
    if (T >= 60) and (T < 300):
        B = (T // 60)
        T = (T % 60)
    if (T < 60):
        C = (T // 10)
        if (T % 10) == 0:
            print("{} {} {}".format(A, B, C))
            break
        else:
            print(-1)
            break

 

특별히 어려운 조건이 없는 문제였다. 최소한의 버튼 클릭 수를 구하기 위해 입력값을 큰 값으로 최대한 나누면 된다. 입력 값이 단위별로 나눌 수 있는 값인지 판단 후 계산을 하고 몫을 출력해주면 된다. 마지막에 10초로 나눴을 때 나머지가 0이 아니면 -1을 출력한다.

반응형

 

 

1946번: 신입 사원

첫째 줄에는 테스트 케이스의 개수 T(1 ≤ T ≤ 20)가 주어진다. 각 테스트 케이스의 첫째 줄에 지원자의 숫자 N(1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 N개 줄에는 각각의 지원자의 서류심사 성��

www.acmicpc.net

 

 

<내 코드>

 

def recruit(num, score):
    min_interview = score[0][1] # 첫번째 지원자 면접 등수
    cnt = 1 # 첫 번째 지원자는 서류점수가 1등이기에 무조건 뽑힘
    for i in range(1, num):  # 1번 ~ n-1번

        if score[i][1] < min_interview:  # 뽑히는 경우
            min_interview = score[i][1] # 더 높은 등수로 변경
            cnt += 1

    return cnt


tests = int(input())

for _ in range(tests):
    num = int(input())
    score = [list(map(int, input().split())) for _ in range(num)]
    score.sort(key=lambda x: x[0])  # 서류 시험 등수 오름차순
    print(recruit(num, score))

 

Python3로 제출하면 시간 초과가 나고, pypy로 제출하니 통과가 됐다. for문을 최대로 줄이려고 해 봤지만 다른 방법을 찾기가 쉽지 않았다.

 

문제 조건

- 다른 모든 지원자와 비교했을 때 서류심사 성적과 면접시험 성적 중 적어도 하나가 다른 지원자보다 떨어지지 않는 자만 선발.

- 즉, 현재 지원자의 서류 성적보다  더 높은 서류 성적을 가진 사람들보다 면접 성적이 높아야 선발된다.

 

따라서 우선 성적을 '서류 성적순'으로 정렬시킨다. 그리고 가장 높은 서류 성적을 가진 사람은 면접이 낮더라도 무조건 선발된다. 그래서 첫 번째 지원자의 면접 성적을 min_interview에 담고 그 값을 다음 사람들과 비교해나간다. 

더 낮은(즉, 더 좋은 면접 성적) 성적을 가진 사람이 있으면 min_interview에 담는다. 그렇게 되면 특정 지원자의 면접시험 성적과 min_interview만 비교해 특정 지원자의 선발 여부를 결정할 수 있게 된다. 왜냐하면 이미 서류 성적순으로 정렬이 됐기에 지나온 지원자들보다 면접 성적만 낮지 않으면 되기 때문이다.

반응형

 

 

2839번: 설탕 배달

문제 상근이는 요즘 설탕공장에서 설탕을 배달하고 있다. 상근이는 지금 사탕가게에 설탕을 정확하게 N킬로그램을 배달해야 한다. 설탕공장에서 만드는 설탕은 봉지에 담겨져 있다. 봉지는 3킬�

www.acmicpc.net

 

<내 코드>

 

sugar = int(input())
result = 0
while sugar != 0:
    if sugar < 0:
        result = -1
        break

    if (sugar % 5) == 0:
        result += (sugar // 5)
        sugar = 0
    else:
        sugar -= 3
        result += 1

print(result)

 

일단 설탕의 무게가 큰 단위인 5로 나눠지면 몫을 result에 담고 설탕 무게를 0으로 만든다. 만약 5로 나눠지지 않는다면 설탕에서 -3을 해주고 result를 1증가시킨다. 그러다 설탕이 0보다 작아지는 경우에는 5, 3으로 나눌 수 없는 값이기 때문에 -1을 출력하고 반복문을 종료한다.

반응형

+ Recent posts