1. 백준 치킨배달[15686]
도시가 주어지고, 도시에는 집과 치킨가게 가 존재한다. 총 m 개의 치킨가게 가 존재할 때 도시에 주어지는 집들로부터 거리가 가장 작은 최솟값의 거리를 구하는 문제이다.
치킨가게 와 집의 거리계산 은 주어지는 좌표 의 차에서 구한 거리이다.
해당 문제 는 주어지는 배열을 사용하지 않고, 치킨집과 집들을 가지고 새로운 거리 배열을 만들어서 해결해 주었다.
다시 말해 행, 열 에는 치킨집과 집들을 배치하고, 해당 거리들을 배열에 담아 해결했다.
func boj15686() {
answer := 1 << 31
var distance [][]int
abs := func(a int) int {
if a < 0 {
return -a
}
return a
}
min := func(a, b int) int {
if a < b {
return a
}
return b
}
minValue := func(include []int, distance [][]int) int {
result := 0
for i := 0; i < len(distance); i++ {
step := 1 << 31
for j := 0; j < len(distance[i]); j++ {
for k := 0; k < len(include); k++ {
if j == include[k] {
step = min(step, distance[i][j])
}
}
}
result += step
}
return result
}
helper := func(num, depth, limit, flag, start int, out []int) {}
helper = func(num, depth, limit, flag, start int, out []int) {
if depth == limit {
answer = min(answer, minValue(out, distance))
return
} else {
for i := start; i < num; i++ {
if flag&(1<<i) == 0 {
helper(num, depth+1, limit, flag|(1<<i), i+1, append(out, i))
}
}
}
}
reader := bufio.NewReader(os.Stdin)
var (
a, b int
)
fmt.Fscanln(reader, &a, &b)
house := make([][]int, 0)
chicken := make([][]int, 0)
for i := 0; i < a; i++ {
for j := 0; j < a; j++ {
var tmp int
fmt.Fscan(reader, &tmp)
if tmp == 1 {
house = append(house, []int{i, j})
} else if tmp == 2 {
chicken = append(chicken, []int{i, j})
}
}
}
distance = make([][]int, len(house))
for i := 0; i < len(house); i++ {
distance[i] = make([]int, len(chicken))
for j := 0; j < len(chicken); j++ {
distance[i][j] = abs(house[i][0]-chicken[j][0]) + abs(house[i][1]-chicken[j][1])
}
}
/**
치킨집의 개수가 최대 13개이므로, 치킨집의 개수에서 M개를 뽑는 조합을 구하면 된다. (13C6) = 1716 * 집이 최대 50개이므로, 1716 * 50 = 85800
*/
helper(len(chicken), 0, b, 0, 0, []int{})
fmt.Println(answer)
}
고에서 제공하는 min, abs는 타입변환이 필요해서 추가적으로 함수를 작성해 주었다.
치킨집, 일반집 은 각각 1,2의 값으로 주어지기 때문에 입력값을 받아옴과 동시에 해당 좌표들을 배열로 만들어주고,
거리를 구하기 위해서 위에서 작성된 자표를 이용해 모든 집과 모든 치킨집의 대한 거리에 대해 배열을 작성해 주었다.
2. 백준 테트로미노 [14500]
왼쪽에 보이는 모양을 맵에다가 놓았을 때 최댓값을 구해야 한다. 단 주어지는 저 도형들은 회전, 대칭 등이 가능하다.
코드가 엄청 길다. 해당되는 상황에 대해 모두 분기를 나눠주다 보니 아무래도 그게 더 심했던 거 같다.
코드보다 그림을 더 많이 그렸던 문제...
func solution() {
reader := bufio.NewReader(os.Stdin)
getMax := func(a, b int) int {
if a > b {
return a
}
return b
}
stick := func(arr [][]int, row, col int) (rs int) {
//right 3steps more
if col+3 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row][col+2]+arr[row][col+3])
}
//down 3steps more
if row+3 < len(arr) {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+2][col]+arr[row+3][col])
}
return rs
}
square := func(arr [][]int, row, col int) (rs int) {
// right 1step down 1step
if row+1 < len(arr) && col+1 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row+1][col]+arr[row+1][col+1])
}
return rs
}
nieun := func(arr [][]int, row, col int) (rs int) {
// right 2steps down 1step
if row+1 < len(arr) && col+2 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+1][col+1]+arr[row+1][col+2])
}
// left 2steps down 1step
if row+1 < len(arr) && col-2 >= 0 {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+1][col-1]+arr[row+1][col-2])
}
// top 1step right 2steps
if row-1 >= 0 && col+2 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row-1][col]+arr[row-1][col+1]+arr[row-1][col+2])
}
// top 1step left 2steps
if row-1 >= 0 && col-2 >= 0 {
rs = getMax(rs, arr[row][col]+arr[row-1][col]+arr[row-1][col-1]+arr[row-1][col-2])
}
//right 1step down 2steps
if row+2 < len(arr) && col+1 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row+1][col+1]+arr[row+2][col+1])
}
//right 1step top 2steps
if row-2 >= 0 && col+1 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row-1][col+1]+arr[row-2][col+1])
}
// left 1step down 2steps
if row+2 < len(arr) && col-1 >= 0 {
rs = getMax(rs, arr[row][col]+arr[row][col-1]+arr[row+1][col-1]+arr[row+2][col-1])
}
// left 1step top 2steps
if row-2 >= 0 && col-1 >= 0 {
rs = getMax(rs, arr[row][col]+arr[row][col-1]+arr[row-1][col-1]+arr[row-2][col-1])
}
return rs
}
triangle := func(arr [][]int, row, col int) (rs int) {
// right 2steps up 1step
if row-1 >= 0 && col+2 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row][col+2]+arr[row-1][col+1])
}
//right 2steps down 1step
if row+1 < len(arr) && col+2 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row][col+2]+arr[row+1][col+1])
}
// down 2steps right 1step
if row+2 < len(arr) && col+1 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+2][col]+arr[row+1][col+1])
}
// down 2steps left 1step
if row+2 < len(arr) && col-1 >= 0 {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+2][col]+arr[row+1][col-1])
}
return rs
}
etc := func(arr [][]int, row, col int) (rs int) {
// right 2steps up 1step
if row-1 >= 0 && col+2 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row-1][col+1]+arr[row-1][col+2])
}
//right 2steps down 1step
if row+1 < len(arr) && col+2 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row][col+1]+arr[row+1][col+1]+arr[row+1][col+2])
}
//down 2steps right 1step
if row+2 < len(arr) && col+1 < len(arr[0]) {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+1][col+1]+arr[row+2][col+1])
}
//down2steps left 1step
if row+2 < len(arr) && col-1 >= 0 {
rs = getMax(rs, arr[row][col]+arr[row+1][col]+arr[row+1][col-1]+arr[row+2][col-1])
}
return rs
}
check := func(arr [][]int, row, col int) int {
result := getMax(square(arr, row, col), stick(arr, row, col))
result2 := getMax(nieun(arr, row, col), triangle(arr, row, col))
return getMax(result, getMax(result2, etc(arr, row, col)))
}
var answer int
helper := func(arr [][]int, size int) {}
helper = func(arr [][]int, size int) {
if size == len(arr[0])*len(arr) {
return
}
row, col := size/len(arr[0]), size%len(arr[0])
answer = getMax(answer, check(arr, row, col))
helper(arr, size+1)
}
var n, m int
fmt.Fscanln(reader, &n, &m)
arr := make([][]int, n)
for i := range arr {
arr[i] = make([]int, m)
for j := range arr[i] {
fmt.Fscan(reader, &arr[i][j])
}
}
helper(arr, 0)
fmt.Println(answer)
}
단순 코드가 길어서 그렇지 해당되는 모든 케이스에 대해서 잘 정리만 해준다면 일반적인 dfs처럼 좌표의 1번부터 수행하면 된다.
개인적으로 이렇게 좌표탐색을 할 때는 row, col을 넘겨주는거보다 하나의 숫자를 넘겨 row,col 을 계산하는 것이 훨씬 깔끔하다. 예전 스도쿠 문제 풀면서 다른 사람 풀이 중에 이런 부분이 있어 바로 차용해서 이제는 저렇게 숫자로 넘기는 게 더 편하다.
이번주는 생각보다 문제를 많이 풀지 못했다. 아침에 가면 문의 답변 해야 할게 생각보다 있어 오전시간에는 거의 풀지 못했다.
다만 지난주보다 마음에 들었던 점은 해당 두 문제에 대해서 바로 한 번에 통과해서 기분이 무척 좋았다.
'PS > Boj' 카테고리의 다른 글
백준-완탐 연습(Brute-Force) (0) | 2023.08.14 |
---|---|
백준 1251 단어나누기[Java] (0) | 2022.06.26 |
백준 1120 문자열[Java] (0) | 2022.06.26 |
백준 10448 유레카[Java] (0) | 2022.06.26 |