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

 

코딩테스트 연습 - 12주차

XX게임에는 피로도 시스템(0 이상의 정수로 표현합니다)이 있으며, 일정 피로도를 사용해서 던전을 탐험할 수 있습니다. 이때, 각 던전마다 탐험을 시작하기 위해 필요한 "최소 필요 피로도"와 던

programmers.co.kr

 


풀이 과정


  1. 던전의 수가 최대 8개까지밖에 없으므로 모든 조합을 다 해보는게 제일 쉬울것이라 판단
  2. 배열의 인덱스가 2까지 있다고 하면 가능한 케이스는
    1. (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)
    2. 위 케이스를 하나씩 해보면서 탐험 가능한 최대 던전 수를 갱신하는 방식으로 풀이를 진행하면 된다.
    3. 초기 피로도를 k로 잡고, 현재 던전의 최소 필요 피로도보다 현재 피로도가 클 때, 던전의 수를 하나 늘리고 현재 피로도에서 현재 던전의 소모 피로도를 빼주는 방식으로 진행한다. 물론 최소 필요 피로도가 더 크다면 생략
  3. recursion으로 구현하여도 되지만, 파이썬의 permutations 함수를 사용하는것이 가장 간편하다고 생각됨.

소스 코드


from itertools import permutations

def solution(k, dungeons):
    answer = -1
    total_index = [i for i in range(len(dungeons))]
    total_case = list(permutations(total_index, len(dungeons)))
    
    for each_case in total_case:
        fatigue = k
        dungeon_count = 0
        
        for dungeon_idx in each_case:
            if fatigue >= dungeons[dungeon_idx][0]:
                dungeon_count += 1
                fatigue -= dungeons[dungeon_idx][1]
        
        answer = max(answer, dungeon_count)
    
    return answer

https://www.acmicpc.net/problem/2304

 

2304번: 창고 다각형

첫 줄에는 기둥의 개수를 나타내는 정수 N이 주어진다. N은 1 이상 1,000 이하이다. 그 다음 N 개의 줄에는 각 줄에 각 기둥의 왼쪽 면의 위치를 나타내는 정수 L과 높이를 나타내는 정수 H가 한 개의

www.acmicpc.net

 


풀이 과정


  1. 왼쪽 구간을 왼쪽에서 오른쪽으로 진행하면서 최대 높이가 되기 전까지 높이가 높아질때마다 스택에 넣어준다.
    • 구간을 구해주어야 하므로, 스택의 맨 마지막에는 최대 높이가 될 때의 지점도 저장해 준다.
  2. 오른쪽 구간을 오른쪽에서 왼쪽으로 진행하면서 최대 높이가 되기 전까지 높이가 높아질때마다 스택에 넣어준다.
    • 구간을 구해주어야 하므로, 스택의 맨 마지막에는 최대 높이가 될 때의 지점도 저장해 준다.
  3. (1)번과 (2)번 스택을 활용하여 왼쪽 구간과 오른쪽 구간의 넓이를 구해준다.
  4. 마지막으로, 최대 높이 구간 넓이를 구해서 더해준다.
    1. 왼쪽 -> 오른쪽으로 찾았을때의 최대 높이가 되는 지점
    2. 오른쪽 -> 왼쪽으로 찾았을 때의 최대 높이가 되는 지점
    3. (2)에서 (1)을 빼준 값에 1을 더한 값이 최대 높이에서의 구간 합이다.

소스 코드


import sys
from bisect import bisect_left, bisect_right

input = lambda: sys.stdin.readline().rstrip()

N = int(input())
block = []

for _ in range(N):
    L, H = map(int, input().split())
    block.append([L, H])

def rfind(arr, a):
    for i in range(len(arr)-1, -1, -1):
        if arr[i] == a:
            return i
    return -1

def lfind(arr, a):
    for i in range(len(arr)):
        if arr[i] == a:
            return i
    return -1

block.sort(key=lambda x:x[0])
block_value = list(map(lambda x:x[1], block))
max_block_value = max(block_value)
left = []
right = []
p = 0

# 왼쪽 구간 저장
while p < len(block) and block[p][1] != max_block_value:
    if not left:
        left.append(block[p])
    elif left and left[-1][1] <= block[p][1]:
        left.append(block[p])
    p += 1
    
left.append(block[p])

# 오른쪽 구간 저장
p = len(block)-1
while p >= 0 and block[p][1] != max_block_value:
    if not right:
        right.append(block[p])
    elif right and right[-1][1] <= block[p][1]:
        right.append(block[p])
    p -= 1

right.append(block[p])
right.sort(key = lambda x:x[0])

area = 0
# 왼쪽 구간 너비 합
for i in range(1, len(left)):
    area += left[i-1][1] * (left[i][0] - left[i-1][0])

# 오른쪽 구간 너비 합
for i in range(1, len(right)):
    area += right[i][1] * (right[i][0] - right[i-1][0])

# 높이가 가장 큰 부분의 너비 합
lindex = lfind(block_value, max_block_value)
rindex = rfind(block_value, max_block_value)
area += max_block_value * (block[rindex][0] - block[lindex][0] + 1)

print(area)

 

https://www.acmicpc.net/problem/9324

 

9324번: 진짜 메시지

스파이들은 사령부와 통신하기 위해서 SMTP(비밀 메시지 전송 프로토콜)를 사용해 비밀 회선으로 전자 메시지를 보낸다. 메시지가 적들에 의해 조작되어 보내진 것이 아닌 진짜 메시지라는 것

www.acmicpc.net


풀이 과정


  1. 입력받은 문자열을 왼쪽에서 오른쪽으로 하나의 문자씩 진행한다.
  2. 문자의 개수를 카운팅하다가 문자의 개수가 0이 아닌 3의 배수가 된다면, 다음에 나와야 하는 문자는 해당 문자가 되어야 한다.
  3. 따라서, 따로 플래그를 두어 개수가 3의 배수가 될 때의 문자를 저장해 두고, 바로 다음 문자가 해당 문자인지 체크하면 된다.
  4. 맨 마지막이 3의 배수가 딱 될때의 케이스는 따로 빼서 처리해 준다.
  5. 경우에 따라 OK, FAKE 출력

소스 코드


import sys
from collections import defaultdict

input = lambda: sys.stdin.readline().rstrip()
n = int(input())
for i in range(n):
    M = input()
    counter = defaultdict(lambda: 0)

    check = True
    next_flg = False
    next_chr = ''
    for ch in M:
        if not check:
            break
        if next_flg:
            if ch != next_chr:
                check = False
            next_flg = False
            continue
        counter[ch] += 1
        if counter[ch] % 3 == 0:
            next_flg = True
            next_chr = ch
    # 다음에 문자가 하나 더 나와야 하는 경우
    if next_flg:
        check = False
    
    if check:
        print("OK")
    else:
        print("FAKE")

  

https://www.acmicpc.net/problem/1261

 

1261번: 알고스팟

첫째 줄에 미로의 크기를 나타내는 가로 크기 M, 세로 크기 N (1 ≤ N, M ≤ 100)이 주어진다. 다음 N개의 줄에는 미로의 상태를 나타내는 숫자 0과 1이 주어진다. 0은 빈 방을 의미하고, 1은 벽을 의미

www.acmicpc.net

 

풀이 과정


  1. 다른때와 다르게, 최단 경로를 저장하는 distance를 2차원 배열로 지정해주어야 해서 특이한 경험이었음.
  2. [0, 0]에서 시작하여 현재 이동할 수 있는 좌표 중 가장 최소로 벽을 부수어야 하는 좌표로 먼저 이동하여 갱신한다.
    • 상,하,좌,우로 이동하면서 거리 갱신이 가능한 경우 최소 히프에 넣어주는 방식으로 구현
    • 벽이 있는 경우는 1을 더해주고, 벽이 없는 경우는 0을 더해주는데, 그냥 입력 배열에 저장되어있는 값을 더해준다.
  3. 마지막에, distance[N-1][M-1]을 출력해준다.
  4. 원래 이런 문제는 BFS로만 풀었었는데 다익스트라 알고리즘으로도 풀리네..  BFS로 풀면 중복이 훨씬 많이 일어나서 비효율적이긴 할듯.

소스 코드


import sys
import heapq

input = lambda: sys.stdin.readline().rstrip()

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

matrix = [list(map(int, list(input()))) for _ in range(N)]
distance = [[int(10e9)] * M for _ in range(N)]
distance[0][0] = 0

heap = []
heapq.heappush(heap, [0, 0, 0])

dx = [-1, 1, 0, 0]
dy = [0, 0, 1, -1]

while heap:
    dist, x, y = heapq.heappop(heap)
    if distance[x][y] != dist:
        continue

    for i in range(4):
        nx, ny = x+dx[i], y+dy[i]
        if 0 <= nx and nx < N and 0 <= ny and ny < M:
            if distance[nx][ny] > dist + matrix[nx][ny]:
                distance[nx][ny] = dist + matrix[nx][ny]
                heapq.heappush(heap, [distance[nx][ny], nx, ny])


print(distance[N-1][M-1])

https://www.acmicpc.net/problem/1987

 

1987번: 알파벳

세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으

www.acmicpc.net

 


풀이 과정


  1. 처음엔 그냥 무턱대고 BFS로 풀이를 진행하였으나.. 큐에 데이터가 너무 많이 들어가게 되서 그런지 메모리 초과가 계속해서 발생하였다ㅜㅜ
  2. 그래서 BFS처럼 큐에 데이터가 가득 쌓이지는 않으니까 DFS로 풀이를 바꾸어서 진행하였다.
    1. 현재 위치에서 동,서,남,북으로 다음 위치로 이동할 때, 다음 위치에 있는 말이 이전까지 방문한 알파벳에 포함되어있지 않다면 DFS 진행
    2. 재귀함수를 호출하면서 다음 방문 위치와 현재 방문한 알파벳들도 같이 넘겨주어야 한다.
    3. DFS를 진행하면서 최대 이동 거리를 계속해서 갱신시켜준다. 
  3. 큐에 데이터가 많이 쌓이게 되면 메모리 초과가 발생하니 BFS뿐 아니라 DFS로도 풀이를 해야 하는걸 배움. 또한 방문처리 할때 set 자료구조에 너무 의존하지 말고, 알파벳은 최대 26개이니까 방문 알파벳들을 문자열로 쭉 연결한 다음 set 연산자가 아닌 in 연산자를 사용하여도 크게 문제될 건 없어보임.

소스 코드


import sys

input = lambda: sys.stdin.readline().rstrip()
R, C = map(int, input().split())

matrix = [list(input()) for _ in range(R)]
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
answer = 0

def solve(visited_str, x, y):
    global R, C
    skip = True
    answer = 0
    for i in range(4):
        nx = x + dx[i]
        ny = y + dy[i]
        if 0 <= nx and nx < R and 0 <= ny and ny < C:
            if matrix[nx][ny] not in visited_str:
                skip = False
                answer = max(answer,
                             1 + solve(visited_str + matrix[nx][ny], nx, ny))

    if skip:
        return 1
    else:
        return answer

print(solve(matrix[0][0], 0, 0))

Import


from django.db.models import Q, F

Q object


  • Django DB 관련 작업에서 사용할 수 있는 SQL 조건문

  • filter 메서드에서 주로 사용

  • OR이나 AND 연산자나 NOT 연산자를 사용하여 조건을 정의하기 위해 사용된다.

      Question.objects.filter(Q(subject__icontains=query) or Q(content__icontains=query))
    • 각 조건을 Q object로 만들고, 두개의 Q object를 각각 or 연산
    • or( | ), and( & ), not( ~ )

F Object

  • 쿼리 내에서 모델 필드 접근할 때 사용
  • 모델 필드나 annotated column의 값을 가져올 때 사용된다.
from django.db.models import F
Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks'))
  • 표현식과 함께 사용할 때는 반드시 유의해야 한다.
    • F 함수를 만나게 되면 캡슐화된 SQL문을 생성하기 위해 파이썬 연산자를 오버라이딩 한다.
# Tintin filed a news story!
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed += 1
reporter.save()

###############################################

from django.db.models import F

reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()

# reporter.refresh_from_db(fields=['stories_filed'])

reporter.name = 'Tintin Jr.'
reporter.save() # 
  • 위 소스를 아래 소스로 바꾸려고 하는건데.. 문제가 있다.
  • 아래 소스는 F('stories_filed') + 1 자체를 SQL Syntax로 만들어버려서 reporter.stories_filed의 값이 1 증가하는 쿼리가 실행된다. 이 때, reporter.stories_filed의 값을 갱신하는것이 아님. 데이터베이스 자체의 SQL문 실행
  • reporter.stories_filed 값을 실제 저장된 값으로 업데이트하기 위해선 모델을 데이터베이스에서 다시 불러와주어야 한다.
  • F Object는 save() 이후에도 모델에 남아있는 문제가 있으며, 각 save()에 적용된다. 따라서 초기 값이 1이라고 할 때, 처음 save 연산자를 해주면 SQL문이 실행되어 2가 되는데, 다음에 또 save 연산을 해주면 또 SQL문이 실행되어 3이 된다.이 과정을 해결해주기 위해서는 refresh_from_db()를 사용해주면 된다.
    • Model.refresh_from_db(using=None, fields=None)

pk

  • get을 할때, pk로 입력하나 id로 입력하나 같은 결과가 나온다.
  • pk가 id__exact와 같다고 한다.
model.objects.get(id=1)
model.objects.get(pk=1)

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] Session  (0) 2021.10.17
[ Django ] CSRFToken  (0) 2021.10.16
[ Django ] JWT(djangorestframework-simplejwt)  (0) 2021.10.15
[ Django ] JWT  (0) 2021.10.14
[ Django ] Choice  (0) 2021.09.15

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

 

코딩테스트 연습 - 11주차

[[1,1,7,4],[3,2,5,5],[4,3,6,9],[2,6,8,8]] 1 3 7 8 17 [[1,1,8,4],[2,2,4,9],[3,6,9,8],[6,3,7,7]] 9 7 6 1 11 [[2,2,5,5],[1,3,6,4],[3,1,4,6]] 1 4 6 3 10

programmers.co.kr

 


풀이 과정


구현 문제 겁나 어렵네

  1. 풀이 이후 다른 사람들의 해결 방법을 보니 여러 해결방법이 있는것 같다.. 일단 본인은 직선 단위로 풀이를 진행함.
  2. 각각의 직사각형을 4개의 직선으로 나누어서 저장.
  3. 직선을 저장할 때, 다른 직선과의 교점이 발생할 경우, 해당 직선을 교점을 기준으로 나누어서 저장
    1. 교점 기준으로 왼쪽, 오른쪽, 위, 아래 총 네개의 직선이 나온다.
    2. 나누어진 직선이 또 다른 직선과의 교점이 발생할 수 있으므로 이 과정은 recursion으로 진행
  4. 직선들 중 직선이 도형 내부에 존재하는 경우를 빼준다.
  5. 시작점에서부터 BFS를 진행하여 도착 지점까지의 최소 거리를 구해준다.
  6. 최소 거리를 리턴해주면 된다.

말은 쉽게 했지만.. 과정 하나하나 직접 코딩할 때 생각보다 시간이 훨씬 많이 걸려 3시간정도 걸린것 같다. 물론 이것도 변이 겹치는 경우가 없어서 위같이 풀이를 할 수 있었음. 구현 문제 연습을 조금 더 많이 해야할 것 같다..


소스 코드


"""
	nbalance97.tistory.com
"""

import sys
from collections import defaultdict, deque

sys.setrecursionlimit(10**5)

def get_cross_point(lineA, lineB):
    p1_x, p1_y, p2_x, p2_y = lineA
    p3_x, p3_y, p4_x, p4_y = lineB
    
    # 평행인 경우
    if (p1_x == p2_x and p3_x == p4_x) or (p1_y == p2_y and p3_y == p4_y):
        return ()
    
    if p1_x == p2_x: 
        # 세로 직선인 경우
        if (p3_x < p1_x and p1_x < p4_x and p1_y < p3_y and p3_y < p2_y):
            return (p1_x, p3_y)
    else: 
        # 가로 직선인 경우
        if (p3_y < p1_y and p1_y < p4_y and p1_x < p3_x and p3_x < p2_x):
            return (p3_x, p1_y)
    
    return ()

def division(currentline, addline, deleteline, new_line):
    for exist_line in currentline:
        point = get_cross_point(new_line, exist_line)
        if point:
            deleteline.append(exist_line)
            x, y = point
            division(currentline, addline, deleteline, (new_line[0], new_line[1], x, y))
            division(currentline, addline, deleteline, (x, y, new_line[2], new_line[3]))
            division(currentline, addline, deleteline, (exist_line[0], exist_line[1], x, y))
            division(currentline, addline, deleteline, (x, y, exist_line[2], exist_line[3]))
            return

    addline.append(new_line)
        
def solution(rectangle, characterX, characterY, itemX, itemY):
    answer = 0
    line = set()
    
    for x1, y1, x2, y2 in rectangle:
        make_lines = [(min(x1, x2), y1, max(x1, x2), y1), (x2, min(y1, y2), x2, max(y1, y2)), 
                      (min(x1, x2), y2, max(x1, x2), y2), (x1, min(y1, y2), x1, max(y1, y2))]
        for new_line in make_lines:
            delete_line = []
            add_line = []
            
            division(line, add_line, delete_line, new_line)
                    
            for delete in delete_line:
                line.remove(delete)
            
            for add in add_line:
                line.add(add)

    delete_candidate = []
    # 사각형 내부에 직선이 포함되는지 확인
    for x1, y1, x2, y2 in line:
        for r_x1, r_y1, r_x2, r_y2 in rectangle:
            if x1 == x2:
                # 세로
                if r_x1 < x1 and x1 < r_x2 and r_y1 <= y1 and r_y2 >= y2:
                    delete_candidate.append((x1, y1, x2, y2))
                    break
            else:
                # 가로
                if r_y1 < y1 and y1 < r_y2 and r_x1 <= x1 and r_x2 >= x2:
                    delete_candidate.append((x1, y1, x2, y2))
                    break
    
    for candidate in delete_candidate:
        line.remove(candidate)
    
    graph = defaultdict(lambda:[])
    queue = deque()
    visited = set()
    for x1, y1, x2, y2 in line:
        if x1 <= characterX and characterX <= x2 and y1 <= characterY and characterY <= y2:
            queue.append([x1, y1, abs(x1-characterX) + abs(y1-characterY)])
            queue.append([x2, y2, abs(x2-characterX) + abs(y2-characterY)])
            visited.add((x1, y1))
            visited.add((x2, y2))
            
        graph[(x1, y1)].append((x2, y2))
        graph[(x2, y2)].append((x1, y1))
    
    # 이동 파트
    answer = int(10e9)
    while queue:
        x, y, dist = queue.popleft()
        for n_x, n_y in graph[(x, y)]:
            if min(x, n_x) <= itemX and itemX <= max(x, n_x) and \
               min(y, n_y) <= itemY and itemY <= max(y, n_y):
                answer = min(answer, dist + abs(itemX - x) + abs(itemY - y))
                continue
                
            if (n_x, n_y) not in visited:
                queue.append([n_x, n_y, dist + abs(n_x - x) + abs(n_y - y)])
                visited.add((n_x, n_y))
                        
    return answer

https://www.acmicpc.net/problem/1062

 

1062번: 가르침

첫째 줄에 단어의 개수 N과 K가 주어진다. N은 50보다 작거나 같은 자연수이고, K는 26보다 작거나 같은 자연수 또는 0이다. 둘째 줄부터 N개의 줄에 남극 언어의 단어가 주어진다. 단어는 영어 소문

www.acmicpc.net

 


풀이 과정


  1. 일단 기본적으로 anta, tica라는 단어가 들어간다.
    • 여기서, 알파벳 ['a', 'n', 't', 'i', 'c']는 기본적으로 무조건 들어가야 된다는 점을 알 수 있음.
  2. 따라서, K가 5보다 작은 경우는 불가능하므로 0을 출력해주면 되고, 5보다 큰 경우는 두가지로 나눌 수 있다.
    1. 기본적으로 ['a', 'n', 't', 'i', 'c']는 들어가야 함.
    2. (1)에서 제외한 알파벳들 중 (K-5)개를 뽑음.
    3. 1번과 2번을 합치면 하나의 케이스가 된다.
  3. 각각의 케이스별로 총 몇개의 단어를 읽을수 있는지 체크하고, 최댓값을 갱신하면 된다.
  4. 위 과정을 Set 자료구조로 하였는데.. 자꾸 메모리 초과가 나와서 풀이를 좀 찾아보니 비트 마스킹 기법을 사용한다고 한다. 알파벳 위치를 기준으로 비트 '1'을 이동시키는 방식
    • a인 경우 001, b인 경우 010, c인 경우 100, ...  , ab인 경우 011, ...
    • 전체 단어들에 대해 각 단어들을 알파벳 별로 미리 비트화를 시켜준다. 
      • hello의 경우, 알파벳이 h,e,l,o가 있으므로 대응되는 비트값을 1로 수정
    • 각각의 케이스 비교단계에서 케이스 또한 비트화를 시켜준 다음 and 연산자를 해준다.
      • 케이스에서 ['a', 'n', 't', 'i', 'c', 'k']를 뽑았다고 할 때,  단어가 antic인 경우 모두 공통적으로 a, n, t, i, c의 비트가 1로 조정되어 있으므로, and연산자를 해주면 a,n,t,i,c에만 1로 지정되어 있을 것이다.
    • and 연산자의 결과가 케이스의 비트와 같은 경우 읽을 수 있는 단어이므로 카운팅

비트 마스킹이 set보다는 빠르므로 set이 속도 문제로 안된다면, 고려해보아야 한다는걸 배우게 되었다..


소스 코드


import sys
from itertools import combinations

input = lambda: sys.stdin.readline().rstrip()
N, K = map(int, input().split())
words = [0] * N
base = ['a', 'n', 't', 'i', 'c']
for i in range(N):
    word = list(input())[4:-4]
    for ch in word:
        words[i] |= (1 << ord(ch) - ord('a'))
        
answer = 0
if K < 5:
    pass
else:
    alpha = 'bdefghjklmopqrsuvwxyz'
    append_case = list(combinations(list(alpha), K-5))
    for case in append_case:
        make_bit = 0
        for ch in base:
            make_bit |= (1 << ord(ch) - ord('a'))
        for ch in case:
            make_bit |= (1 << ord(ch) - ord('a'))

        count = 0
        for i in range(len(words)):
            if words[i] & make_bit == words[i]:
                count += 1
        
        answer = max(answer, count)
        
print(answer)

전반적인 세션 개념

  • HTTP에서는 새로운 페이지를 요청할 때마다 새로운 연결하여 상태유지가 되지 않음.
  • 사용자의 상태를 유지하기 위해 쿠키와 세션 사용
    • 브라우저마다 상태 저장
  • 세션의 데이터(사용자의 데이터)는 서버에 저장된다.
  • 서버에서는 세션에 데이터를 저장하고, 세션ID를 쿠키로 클라이언트에 발급한다. (Set-cookie)
  • 클라이언트는 발급받는 세션ID를 쿠키에 저장한다.
  • https://developer.mozilla.org/ko/docs/Learn/Server-side/Django/Sessions

세션의 장점

  • 서버에 사용자의 데이터를 저장하므로 보안상 우수

세션의 단점

  • 서버에 사용자의 데이터를 저장하므로 서버의 부하 증가

Django에서의 Session


  • 세션에 데이터를 저장하기 전까지는 Sessionid를 따로 클라이언트에 전송하지 않음.
  • 세션에 데이터를 저장하는 순간부터 Sessionid를 클라이언트에 전달
  • Django에서의 세션 사용법
def f(request):
    ...
    request.session['저장할 데이터명'] = 값
  • request.session : 현재 사용자/브라우저에 대한 세션, 딕셔너리처럼 사용 가능
  • 세션에 데이터를 간접적으로 저장한 경우 따로 Django에 modified를 설정하여 데이터를 저장했음을 알려주어야 함.
    • 예를들면 session에 리스트가 저장되어 있고, 리스트의 요소중 하나의 값을 바꿧다던지..
request.session.modified = True

Session 관련 Setting 몇가지(Settings.py)


  1. SESSION_COOKIE_AGE
    • 세션 쿠키 지속기간(초), 기본값은 2주
  2. SESSION_COOKIE_HTTPONLY
    • 세션 쿠키에 HttpOnly 설정, 기본값은 True
    • 세션 쿠키를 JavaScript에서 읽는건 문제가 될 수 있으므로 False를 굳이??
  3. SESSION_COOKIE_NAME
    • 세션 쿠키의 이름, 기본값은 sessionid
  4. SESSION_COOKIE_PATH
    • 세션 쿠키의 경로, 기본값은 /
  5. SESSION_COOKIE_SECURE
    • SECURE 옵션 사용여부, https를 사용한다면 True로 하는게 좋음.
    • 기본값은 False
  6. SESSION_SAVE_EVERY_REQUEST
    • 모든 request의 session 데이터 저장
    • 원래는 session 데이터가 변경된 경우에만 저장
    • session이 텅 빈 경우는 True라 하더라도 생성되지 않음.

'프레임워크 > Django' 카테고리의 다른 글

[ Django ] Q, F object  (0) 2021.10.20
[ Django ] CSRFToken  (0) 2021.10.16
[ Django ] JWT(djangorestframework-simplejwt)  (0) 2021.10.15
[ Django ] JWT  (0) 2021.10.14
[ Django ] Choice  (0) 2021.09.15

https://www.acmicpc.net/problem/3079

 

3079번: 입국심사

첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 100,000, 1 ≤ M ≤ 1,000,000,000) 다음 N개 줄에는 각 심사대에서 심사를 하는데 걸리는 시간인 Tk가 주어진다. (1 ≤ Tk ≤ 109)

www.acmicpc.net

 


풀이 과정


  1. 보면 N값과 M값이 굉장히 크기 때문에 전수조사 하게 되는 경우 시간초과가 100% 날거라 생각됨.
  2. 따라서, 친구들이 심사를 받는데 걸리는 시간을 기준으로 이분탐색을 진행함.
  3. 범위는 최소 0, 최대 1000000000 * 10^9를 잡아주어야 한다. 
    • 이유는 입국심사대에 1명이 있으며, 친구들이 1000000000명, 그리고 걸리는 시간이 10^9인 경우를 고려
  4. 중간값을 기준으로 중간값일때 심사받는 친구의 수가 M보다 크거나 같으면 시간을 줄여야 하므로 정답 저장후 왼쪽 구간, M보다 작은 경우는 정답을 저장하진 말고 오른쪽 구간을 진행하면 된다.
  5. 저장된 정답을 출력해 준다.

소스 코드


 

import sys

input = lambda : sys.stdin.readline().rstrip()
N, M = map(int, input().split())
T = [int(input()) for _ in range(N)]

left = 0
right = (1000000000 * int(10e9)) + 1
answer = 0
while left <= right:
    mid = (left + right) // 2

    # 중간값일때, 심사받는 사람의 수 구함
    evaluated_people_count = 0
    for time in T:
        evaluated_people_count += (mid // time)

    # 심사받는 사람의 수가 M보다 작으면 시간을 늘려야 하므로 오른쪽 구간
    # M보다 크거나 같으면 시간을 줄여야 하므로 왼쪽 구간
    if evaluated_people_count >= M:
        answer = mid
        right = mid - 1
    else:
        left = mid + 1

print(answer)

+ Recent posts