숫자 게임

Problem

https://www.algospot.com/judge/problem/read/NUMBERGAME

Idea

게임의 상태가 변경된다 A와 B 게임 순서가 존재 A와 B중 누가 이기는가 A와 B 게임 점수차가 최대인 경우

A 차례의 게임 상태에 따른 최대 점수차 = 이전의 B 차례의 게임 상태에 따른 최대 점수차 + 게임 상태 변경 delta

f(state): 현재 게임판 상태에 따른 두사람의 최대 점수 차 로 정의 한다면:

A차례 일 경우 A 최대값 = A 선택 - B 최대값 직전의 B 차례의 일 경우 B 최대 값 = B 선택 - A의 최대 값 = -f(state)

f(1, n) = max (
    board(0,1) - f(2, n), // 가장왼쪽 선택
    board(n-1, n) - f(1, n-1), // 가장 오른쪽 선택
    0 - f(3, n), // 왼쪽 2개 제거 if (n-1 >= 1) // 버리는 카드니 점수에 영향없음
    0 - f(1, n-2) // 오른쪽 2개 제거 if (n-1 >= 1)
)
블록 게임

Problem

https://algospot.com/judge/problem/read/NUMB3RS

Idea

http://confluence.score/pages/viewpage.action?pageId=41167601

사다리 개임

Problem

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

Summary

사다리 타기게임에서 사다리를 추가/제거 해서 원하는 목적지로 가고자한다
사다리를 조작할 때, 최소비용을 구해본다

Idea

가로/세로선의 상태에 따라 값이 다르다

블록 게임

Problem

https://www.algospot.com/judge/problem/read/BLOCKGAME

Idea

지금이 누구차례인지 알 필요없다
놓여있는 블록배치 알 필요없다
각 칸에 블록이있냐 없냐만 알면 승패는 정해진다

f(board) = 현재 게임판의 상태가 board일 때 이번차례사람이 이길 방법이 있는지 반환

http://confluence.score/pages/viewpage.action?pageId=41169842

외판원 순회

Problem

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

Summary

한 외판원이 어느 한 도시에서 출발해 N개의 도시를 모두 거쳐 다시 원래의 도시로 돌아오는 순회 여행 경로
중 가장 적은 비용을 들이는 여행 경로구하기 도시의 수 N (2<=N<=16)

Idea

각 도시를 전체 순회해보는 방법은 N! 가지가 된다. 10!는3628800 이며 11!는 39916800이다.

전체 탐색

static private void TSP(int curr, ArrayList<Integer> path, int sum) {
    if (path.size() == N) {
        int ret = W[curr][path.get(0)];
        if (ret == 0) {
            return;
        }
        sum += ret;
        if (min > sum) {
            min = sum;
        }
        return;
    }

    for (int i = 0; i < N; i++) {
        if (curr == i || W[curr][i] == 0) {
            continue;
        }

        if (visited[i] == false) {
            visited[i] = true;
            path.add(i);
            TSP(i, path, sum + W[curr][i]);
            visited[i] = false;
            path.remove(path.size()-1);
        }
    }
}

DP

방문도시 1->2->3->4->5 와 1->2->3->5->4 로 순회 시 1->2->3은 이미 방문했던 길로 중복 체크 될 수 있다

f(N (시작점)에서 출발해서 모든 도시를 방문할 때 드는 최소 비용.
f(N, {N-1,N-2….1}) = cost(N,N-1) + f(N-1, {N-2,N-3,….1})

dp[1][0000 1110(=14)] = f(1, {2,3,4}) ==> 도시 1에서 2,3,4를 순회하는 최소비용
dp[2][0000 1101(=13)] = f(2, {1,3,4}) ==> 도시 2에서 1,3,4를 순회하는 최소비용

visited 표현 시 bit operation 활용

  • 전체집합 (1«20) -1
  • p번 원소 추가 set |= (1«p)
  • p번 원소 확인: p번 원소를 켜있는지 확인 set & (1«p)
  • p번 원소 삭제: p번 원소를 끈다 set &= ~(1«p)
  • p번 원소 토글: p번 원소가 켜있으면 끄고, 꺼있으면 킨다 set ^= (1«p)
int min = Integer.MAX_VALUE;
for (int i = 1 ; i <= N; i++) {
    end = i;
    min = Math.min(min, TSP(i, 1 << (i-1)));
}

static private int TSP(int curr, int visited) {

    if (visited == (1<< (N+1)) - 1) {
        return W[curr][end];
    }
    int ret = 0;
    ret = cached[curr][visited];
    if (ret != 0) {
        return ret;
    }

    ret = Integer.MAX;

    for (int i = 1; i <= N; i++) {
        if (curr == i || W[curr][i] == 0) {
            continue;
        }
        if ((visited & (1 << i)) > 0) {
            continue;
        }

        //ret = Math.min(ret, TSP(i, visited | 1 << i) + W[curr][i]);
        if (ret > TSP(i, visited | 1 << i) + W[curr][i]) {
            ret = TSP(i, visited | 1 << i) + W[curr][i];
        }
    }
    cached[curr][visited] = ret;
    return cached[curr][visited];
}

부분 문제 수: N(노드수) * 2^N (방문체크), tsp 내에서의 반복 = N^2 * 2^N

경로 추적