def Innerbound(x,y):
if 0<=x<N and 0<=y<M:
return True
else:
return False
def dfs(idx,bit,total):
global result
if bit == 2**(N*M)-1:
result = max(result,total)
return
else:
if 2**idx&bit:
dfs(idx+1,bit,total)
else:
x,y = idx//M, idx%M
nx,ny = x,y
temp_bit = bit
temp_num = 0
while Innerbound(nx,ny):
if visited[nx][ny]:
next_idx = nx*M + ny
visited[nx][ny] = False
temp_bit = temp_bit|(2**next_idx)
temp_num = temp_num*10 + arr[nx][ny]
nx = nx + 1
ny = ny
else:
break
for rx in range(nx-1,x-1,-1):
dfs(idx+1,temp_bit,total + temp_num)
temp_num = temp_num//10
next_idx = rx*M + y
temp_bit = temp_bit^(2**next_idx)
visited[rx][y] = True
nx,ny = x,y
temp_bit = bit
temp_num = 0
while Innerbound(nx,ny):
if visited[nx][ny]:
next_idx = nx*M + ny
visited[nx][ny] = False
temp_bit = temp_bit|(2**next_idx)
temp_num = temp_num*10 + arr[nx][ny]
nx = nx
ny = ny + 1
else:
break
for ry in range(ny-1,y-1,-1):
dfs(idx+1,temp_bit,total + temp_num)
temp_num = temp_num//10
next_idx = x*M + ry
temp_bit = temp_bit^(2**next_idx)
visited[x][ry] = True
N,M = map(int,input().split())
arr = [list(map(int,list(input()))) for _ in range(N)]
visited = [[True for _ in range(M)] for _ in range(N)]
result = 0
dfs(0,0,0)
print(result)

 

 

처음에 모든 경우들을 각각 하나씩 그려보면서 dfs를 해주었다.

 

가로 혹은 세로로 최대한 세울 수 있는 직사각형을 그려주고 그때부터 dfs를 하고 하나씩 내려주면서 dfs를 해주었다.

 

이 방식은 오래걸리는 방식이였고, 다른 사람들의 풀이를 보고 다시 푼 방식은 다음과 같다.

 

N,M = map(int,input().split())
arr = [list(map(int,list(input()))) for _ in range(N)]
result = 0
# 0은 가로인걸로 1은 세로인걸로 판별
for bit_shape in range(2**(N*M)):
total_sum = 0
for x in range(N):
sub_sum = 0 # 작은 단위의 SUM
for y in range(M):
idx = x*M + y
if not bit_shape & (1<<idx):
sub_sum = sub_sum*10 + arr[x][y]
else:
total_sum += sub_sum
sub_sum = 0
total_sum += sub_sum
for y in range(M):
sub_sum = 0
for x in range(N):
idx = x*M + y
if bit_shape & (1<<idx):
sub_sum = sub_sum*10 + arr[x][y]
else:
total_sum += sub_sum
sub_sum = 0
total_sum += sub_sum
result = max(result,total_sum)
print(result)

 

이 방식은 모든 경우를 먼저 구하는 거다. 이 문제는 최대 16개의 칸을 가지는 것이다.

 

이것을 비트로 표현해서 0이면 가로로 그려진 직사각형 1이면 세로인 직사각형으로 구분을 해주는것이다.

 

그러면 우리는 2**(N*M)의 경우의 수를 가질수 있다. 최대 65536가지이므로, 빠르게 구할 수 있다.

 

비트로 현재 종이조각의 상태를 구분하고, 그 상태에 맞게 숫자를 세서 최대값을 구하면 된다.

import sys
from itertools import combinations
def input():
return sys.stdin.readline().rstrip()
N = int(input())
arr = [list(map(int,input().split())) for _ in range(N)]
row = [sum(i) for i in arr]
col = [sum(i) for i in zip(*arr)]
new_arr = [i+ j for i, j in zip(row, col)]
total_sum = sum(new_arr)//2
result = float('inf')
for num in range(1,N//2+1):
for combi in combinations(new_arr,num):
result = min(result,abs(total_sum-sum(combi)))
if result == 0:
break
if result == 0:
break
print(result)

이 문제는 과거에 푼 boj.kr/14889 이 있었기 때문에 빨리 풀 수 있었다. 

 

기본 푼 방식은 원래와 똑같다. 각 col,row의 섬을 미리 구해놓고, 그걸 통해서 문제를 푸는 방식이다.

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ/백준] 16472 고냥이  (0) 2021.06.29
[BOJ/백준] 16398 행성 연결  (0) 2021.06.29
[BOJ/백준] 10711 모래성  (0) 2021.06.29
[BOJ/백준] 2463 비용  (0) 2021.06.29
[BOJ/백준] 1398 동전  (0) 2021.06.29
from itertools import permutations
import sys
input = sys.stdin.readline
def rotate(command,moving_arr):
global arr
cnt = 1
while cnt<=command[2]:
start_row,start_col = command[0]-cnt, command[1]-cnt
end_row,end_col = command[0] + cnt,command[1] + cnt
for row in range(start_row,end_row+1):
if row == start_row or row == end_row:
if row == start_row:
for col in range(start_col,end_col+1):
if col == end_col:
moving_arr[row+1][col] = prev_arr[row][col]
else:
moving_arr[row][col+1] = prev_arr[row][col]
else:
for col in range(end_col,start_col-1,-1):
if col == start_col:
moving_arr[row-1][col] = prev_arr[row][col]
else:
moving_arr[row][col-1] = prev_arr[row][col]
else:
moving_arr[row-1][start_col] = prev_arr[row][start_col]
moving_arr[row+1][end_col] = prev_arr[row][end_col]
cnt += 1
N,M,K = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(N)]
command_list = []
for _ in range(K):
x,y,r = map(int,input().split())
command_list.append((x-1,y-1,r))
result = float('inf')
for commands in permutations(command_list):
move_arr = [row[:] for row in arr]
prev_arr = [row[:] for row in arr]
for command in commands:
rotate(command,move_arr)
prev_arr = [row[:] for row in move_arr]
arr_min = min(list(map(sum,move_arr)))
result = min(arr_min,result)
print(result)

 

 

 

from itertools import permutations
import sys
input = sys.stdin.readline
def rotate(command,move_arr):
x,y,s = command
for i in range(1,s+1):
subtract_data = move_arr[x-i][y-i] # 좌측 최상단 꼭지점을 빼놓기
for r in range(x-i,x+i): # 좌측 세로를 아래에서 위로 올리는 과정
move_arr[r][y-i] = move_arr[r+1][y-i]
for c in range(y-i,y+i):
move_arr[x+i][c] = move_arr[x+i][c+1]
for r in range(x+i,x-i,-1):
move_arr[r][y+i] = move_arr[r-1][y+i]
for c in range(y+i,y-i+1,-1):
move_arr[x-i][c] = move_arr[x-i][c-1]
move_arr[x-i][y-i+1] = subtract_data
N,M,K = map(int,input().split())
arr = [list(map(int,input().split())) for _ in range(N)]
command_list = []
for _ in range(K):
x,y,r = map(int,input().split())
command_list.append((x-1,y-1,r))
result = float('inf')
for commands in permutations(command_list):
move_arr = [row[:] for row in arr]
for command in commands:
rotate(command,move_arr)
arr_min = min(list(map(sum,move_arr)))
result = min(arr_min,result)
print(result)

'알고리즘 > 백준_복기_미완료' 카테고리의 다른 글

[BOJ/백준] 17837 새로운 게임 2  (0) 2021.05.06
[BOJ/백준] 17779 게리맨더링 2  (0) 2021.05.06
[BOJ/백준] 17404 RGB 거리 2  (0) 2021.05.06
[BOJ/백준] 17298 오큰수  (0) 2021.05.06
[BOJ/백준] 17281 ⚾  (0) 2021.05.06
from itertools import permutations
import sys
input = sys.stdin.readline
def play(entry):
out_count = 0
innings = 0
cu_player_ind = 0
# 1루,2루,3루
score = 0
base1,base2,base3 = 0,0,0
while innings < N:
while out_count<3:
if arr[innings][entry[cu_player_ind]-1] == 0:
out_count += 1
elif arr[innings][entry[cu_player_ind]-1] == 1:
score += base3
base1,base2,base3 = 1,base1,base2
elif arr[innings][entry[cu_player_ind]-1] == 2:
score += (base2+base3)
base1,base2,base3 = 0,1,base1
elif arr[innings][entry[cu_player_ind]-1] == 3:
score += (base1+base2+base3)
base1,base2,base3 = 0,0,1
else:
score = score + base1+base2+base3 + 1
base1,base2,base3 = 0,0,0
cu_player_ind = (cu_player_ind+1)%9
out_count = 0
base1,base2,base3 = 0,0,0
innings += 1
return score
N = int(input())
arr = [list(map(int,input().split())) for _ in range(N)]
result = 0
for _players in permutations(range(2,10)):
_players = list(_players)
players = _players[:3]+[1] + _players[3:]
temp = play(players)
if result <temp:
result = temp
print(result)

 

 

from itertools import permutations
import sys
input = sys.stdin.readline
N = int(input())
arr = [list(map(int,input().split())) for _ in range(N)]
result = 0
for _players in permutations(range(2,10)):
_players = list(_players)
players = _players[:3]+[1] + _players[3:]
cu_player_ind = 0
# 1루,2루,3루
score = 0
for innings in arr:
out_count = 0
base1,base2,base3 = 0,0,0
while out_count<3:
if innings[players[cu_player_ind]-1] == 0:
out_count += 1
elif innings[players[cu_player_ind]-1] == 1:
score += base3
base1,base2,base3 = 1,base1,base2
elif innings[players[cu_player_ind]-1] == 2:
score += (base2+base3)
base1,base2,base3 = 0,1,base1
elif innings[players[cu_player_ind]-1] == 3:
score += (base1+base2+base3)
base1,base2,base3 = 0,0,1
else:
score = score + base1+base2+base3 + 1
base1,base2,base3 = 0,0,0
cu_player_ind = (cu_player_ind+1)%9
if score > result:
result = score
print(result)
def dfs(x,y,cnt):
global result
if cnt > result:
return
if x >= 10:
result = min(result,cnt)
return
if y >= 10:
dfs(x+1,0,cnt)
return
if arr[x][y] == 1:
for paper_size in range(5,0,-1):
if paper[paper_size]:
if x + paper_size <= 10 and y + paper_size <= 10:
flag = False
for dx in range(paper_size):
for dy in range(paper_size):
if not arr[x+dx][y+dy]:
flag = True
break
if flag:
break
if not flag:
for dx in range(paper_size):
for dy in range(paper_size):
arr[x+dx][y+dy] = 0
paper[paper_size] -= 1
dfs(x,y+paper_size-1,cnt+1)
paper[paper_size] += 1
for dx in range(paper_size):
for dy in range(paper_size):
arr[x+dx][y+dy] = 1
else:
dfs(x,y+1,cnt)
arr = [list(map(int,input().split())) for _ in range(10)]
paper = [0]+[5]*5
result = float('inf')
dfs(0,0,0)
print(result if result != float('inf') else -1)

 

 

 

def check(x,y,size):
if x + size > 10 or y + size >10:
return False
for dx in range(size):
for dy in range(size):
if not arr[x+dx][y+dy]:
return False
return True
def set_position(x,y,size,val):
for dx in range(size):
for dy in range(size):
arr[x+dx][y+dy] = val
def dfs(x,y,cnt):
global result
if cnt >= result:
return
finish = True
while x < 10:
while y < 10:
if arr[x][y] == 1:
finish = False
for paper_size in range(5,0,-1):
if paper[paper_size] and check(x,y,paper_size):
set_position(x,y,paper_size,0)
paper[paper_size] -= 1
dfs(x,y+paper_size-1,cnt+1)
paper[paper_size] += 1
set_position(x,y,paper_size,1)
return
y += 1
x += 1
y = 0
if finish:
result = min(result,cnt)
arr = [list(map(int,input().split())) for _ in range(10)]
paper = [0]+[5]*5
result = float('inf')
dfs(0,0,0)
print(result if result != float('inf') else -1)
import sys
input = sys.stdin.readline
def calc_operator(operator,x,y):
if operator == '*':
return x*y
elif operator == '-':
return x-y
elif operator == '+':
return x+y
def calc():
new_num_list = []
new_operator_list = []
ind = 0
while ind<len(num_list):
if ind < len(num_list)-1:
if not open_bracket[ind]:
new_num_list.append(num_list[ind])
new_operator_list.append(operator_list[ind])
ind += 1
else:
new_number = calc_operator(operator_list[ind],num_list[ind],num_list[ind+1])
if ind == len(num_list)-2:
new_num_list.append(new_number)
else:
new_num_list.append(new_number)
new_operator_list.append(operator_list[ind+1])
ind += 2
else:
new_num_list.append(num_list[ind])
ind+= 1
ind = 0
value = new_num_list[0]
while ind < len(new_num_list)-1:
value = calc_operator(new_operator_list[ind],value,new_num_list[ind+1])
ind += 1
return value
def dfs(index):
global result
if index == len(num_list)-1:
result = max(calc(),result)
return
else:
if visited[index]:
visited[index] = False
visited[index+1] = False
open_bracket[index] = True
dfs(index+1)
visited[index] = True
visited[index+1] = True
open_bracket[index] = False
dfs(index+1)
N = int(input())
arr = list(input())
if N == 1:
print(arr[0])
else:
num_list = []
operator_list = []
for i in range(N):
if i%2:
operator_list.append(arr[i])
else:
num_list.append(int(arr[i]))
result = -float('inf')
visited = [True]*len(num_list)
open_bracket = [False]*len(num_list)
dfs(0)
print(result)

 

 

import sys
input = sys.stdin.readline
def calc(operator,x,y):
if operator == '*':
return x*y
elif operator == '-':
return x-y
elif operator == '+':
return x+y
def dfs(idx,value):
global result
if idx == length_num-1:
result = max(result,value)
return
temp = calc(operator_list[idx],value,num_list[idx+1])
dfs(idx+1,temp)
if idx < length_num-2:
next_value = calc(operator_list[idx+1],num_list[idx+1],num_list[idx+2])
temp = calc(operator_list[idx],value,next_value)
dfs(idx+2,temp)
N = int(input())
origin_input = list(input().strip())
num_list = []
operator_list = []
for ind in range(len(origin_input)):
if ind%2:
operator_list.append(origin_input[ind])
else:
num_list.append(int(origin_input[ind]))
result = -float('inf')
length_num = len(num_list)
dfs(0,num_list[0])
print(result)
def find_arr(arr):
global result
for bit_mask in range(2**8):
copy_arr = [row[:] for row in arr]
change_bit = str(bin(bit_mask))[2:].count('1')
if result < change_bit:
continue
for row in range(3):
if bit_mask & (1<<row):
for col in range(3):
copy_arr[row][col] = (copy_arr[row][col]+1)%2
for col in range(3):
if bit_mask & (1<<(col+3)):
for row in range(3):
copy_arr[row][col] = (copy_arr[row][col]+1)%2
if bit_mask & (1<<6):
for row in range(3):
copy_arr[row][row] = (copy_arr[row][row]+1)%2
if bit_mask & (1<<7):
for row in range(3):
copy_arr[row][2-row] = (copy_arr[row][2-row]+1)%2
sum_temp = sum(list(map(sum,copy_arr)))
if sum_temp == 9 or sum_temp == 0:
result = change_bit
T = int(input())
for tc in range(T):
arr = []
result = float('inf')
for _ in range(3):
s = list(input().split())
for i in range(3):
if s[i] == 'T':
s[i] = 1
else:
s[i] = 0
arr.append(s)
cnt = 0
find_arr(arr)
print(-1 if result == float('inf') else result)
def checkminNumber(index,open1,open2):
if index > M-1:
return 0
result = dp[index][open1][open2]
if result != float('inf'):
return result
next_open = output_list[index]
dp[index][open1][open2] = min(abs(open1 - next_open) + checkminNumber(index+1,next_open,open2), abs(open2 - next_open) + checkminNumber(index+1,open1,next_open))
return dp[index][open1][open2]
N = int(input())
open1,open2 = list(map(int,input().split()))
M = int(input())
dp = [[[float('inf')]*(N+1) for _ in range(N+1)] for _ in range(M)]
output_list = []
for _ in range(M):
output_list.append(int(input()))
print(checkminNumber(0,open1,open2))

 

+ Recent posts