검색결과 리스트
Algorithm에 해당되는 글 14건
- 2016.11.21 3683] 고양이와 개 2
- 2016.11.12 1301] 비즈공예
- 2016.10.14 1937] 욕심쟁이 판다
- 2016.09.25 2306] 유전자
- 2016.09.21 8992] 집기 게임(Pickup Game) 1
- 2016.08.20 8462] 배열의 힘 & Mo's Algorithm
- 2016.08.14 1941] 소문난 칠공주
- 2016.07.22 1052] 물병
- 2016.05.07 1328] 고층 빌딩 , 8895] 막대 배치
- 2016.01.01 1007] Vector Matching
글
문제 설명
: N명의 사람과 c마리의 고양이, d마리의 개가 있다.
한사람 당 다음 라운드에 진출시킬 고양이(개)와 탈락시킬 개(고양이)를 선택한다.
어떤 투표들을 반영시켜야 많은 사람들을 만족시킬 수 있을것인가?
문제 풀이
: 그래프 모델링을 다음과 같이 한다.
한쪽에는 고양이를 통과시키려고 했던 사람들, 다른 한쪽으로는 개를 통과시키려고 했던 사람들.
그다음 연결은 어떻게 하냐하면, 의견이 충돌되는 사람들로 연결을 해준다.
즉, A가 통과시키려고 했던 고양이(개)가 B가 떨어뜨리려고 했던 고양이(개)거나,
반대로 A가 떨어뜨리려고 했던 고양이(개)가 B가 통과시키려고 했던 고양이(개)라면 이 둘을 연결해준다.
이렇게 한다면 이분 그래프의 형성이 가능해진다.
그렇다면 이분 매칭을 했을때 나오는 최대값은 무엇을 뜻할까?
생각해보면, 의견이 상충되는 경우에는 한쪽의 의견만이 통과될 수 있다.
(상충되는 의견 두개가 통과된다는건 모순이기 때문이다)
즉, 어느 한쪽을 탈락시키면 충돌은 모두 해결된다.
(누군가를 탈락시키면 나머지 의견들은 수용되기 때문이다)
결국에 모든 충돌(edge)들을 해소시키면서 최대한 적은 사람들을 떨어뜨려야 한다.
예를 들어 A-B, A-C, A-D가 연결되어 있다면, A를 탈락시킴으로써 B,C,D를 만족시킬 수 있다.
A(vertex)를 택함으로써 B,C,D와 의견이 충돌(edge)되는 것들을 모두 해소(cover) 시킨 것이다!!
결국 minimum vertex cover가 된다.
(minimum vertex cover를 간단하게 설명하자면 이분 그래프에서 양쪽 그룹에서 임의의 vertex들을
최소로 선택하면서 연결된 모든 edge들을 색칠(cover)하는 것을 의미한다.)
그리고 쾨닉의 정리에 의해서 minimum vertex cover는 최대 이분 매칭의 값과 동치이다.
이 값을 v라고 하면 답은 N-v가 된다.
(최소한의 사람을 떨어뜨리면 결국 이 값을 빼면 최대의 만족하는 사람이 나온다!)
소스 코드
'BOJ' 카테고리의 다른 글
1301] 비즈공예 (0) | 2016.11.12 |
---|---|
1937] 욕심쟁이 판다 (0) | 2016.10.14 |
2306] 유전자 (0) | 2016.09.25 |
8992] 집기 게임(Pickup Game) (1) | 2016.09.21 |
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
설정
트랙백
댓글
글
문제 설명
: 개수가 정해진 색깔이 다른 구슬들을 일렬로 배치하면서, 연속된 3개의 구슬에는 중복이 일어나지 않게하는
경우의 수를 구하는 문제이다.
7차원 dp로 해결이 가능하다, 5차원은 각 구슬의 사용 개수를 의미하고 나머지 2차원은 이전과 그 이전에 놓인
구슬의 종류를 의미한다.
소스 코드
'BOJ' 카테고리의 다른 글
3683] 고양이와 개 (2) | 2016.11.21 |
---|---|
1937] 욕심쟁이 판다 (0) | 2016.10.14 |
2306] 유전자 (0) | 2016.09.25 |
8992] 집기 게임(Pickup Game) (1) | 2016.09.21 |
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
설정
트랙백
댓글
글
문제 설명
: 임의의 출발점에서 시작해서 동서남북 방향으로 이동하며 가장 긴 내림차순 수열의 길이를 출력.
동적계획법으로 해결이 가능하다.
이동한 다음에는 그 이전 상태를 되돌아가는 경우가 없는 것은 자명하므로, 갱신되지 않은 부분부터
시작해서 구간들을 다 구해나가면 된다.
하나의 경로를 완성시키면 부분 경로들은 메모이제이션을 통해서 다 완성이 된다.
소스 코드
'BOJ' 카테고리의 다른 글
3683] 고양이와 개 (2) | 2016.11.21 |
---|---|
1301] 비즈공예 (0) | 2016.11.12 |
2306] 유전자 (0) | 2016.09.25 |
8992] 집기 게임(Pickup Game) (1) | 2016.09.21 |
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
설정
트랙백
댓글
글
문제 설명
: 문자열 중에 길이 0 이상의 부분 문자열들을 제거해서 최대 길이의 KOI 유전자를 만드는 문제이다.
당연히도, 동적계획법 문제이다. 무엇을 제거하냐에 따라서 KOI 유전자가 달라지기 때문이다.
해결 방법은 두가지이다. 양끝이 a,t 이거나 g,c인 경우를 보거나, 인접한 a,t와 g,c를 보면 된다.
예를 들자면 aatt와 atat가 있다. 전자의 경우 안쪽에서부터 보면 되는 경우이고, 후자의 경우 바깥쪽에서부터
봐야하는 경우이다.
즉, dp(i,j) = 2 + dp(i-1,j-1) ( 만약 a[i],a[j]가 각각 a,t이거나 g,c인 경우 )
그리고 양쪽에서 보지 않았을 경우 가능한 경우들을 모두 잘라내서 보는 후자의 경우 또한 봐주여야 한다.
dp(i,j) = max(dp(i,j), dp(i,k) + dp(k+1,j)) ( i<=k<j )
소스 코드
'BOJ' 카테고리의 다른 글
1301] 비즈공예 (0) | 2016.11.12 |
---|---|
1937] 욕심쟁이 판다 (0) | 2016.10.14 |
8992] 집기 게임(Pickup Game) (1) | 2016.09.21 |
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
1941] 소문난 칠공주 (0) | 2016.08.14 |
설정
트랙백
댓글
글
문제 설명
: 어느 점에서라도 만나게 되는 무게 a인 가로선과 b인 세로선을 집어가면, a*b 만큼의 점수를 획득할 때,
최대로 한 쌍의 선들을 집어가면서, 점수를 크게하는 문제이다.
왼쪽에는 가로 선들의 집합을, 오른쪽에는 세로 선들의 집합인 이분 그래프를 형성 한 뒤,
MCMF 알고리즘을 이용해서 해결이 가능하다.
가로선은 x축에 평행하고 세로선은 y축에 평행하므로 선들이 만나는가에 대해서는 ccw까지 구현 할 필요가 없고,
간단하게 좌표 범위들로만 확인해서 연결 여부만 확인하면 된다.
MCMF 알고리즘 자체가 일단 최대로 유량을 흘려보내는 것이 목적이고, 그러면서 코스트는
최소화 하는 방향으로 작동하기 때문에 이 문제 조건에서는 코스트의 부호를 반대로 해주어서 가중치 그래프를 형성하면 우선순위로 최대로 유량을 흘려보내면서 두번째로 코스트 또한 큰 방향으로 구해낼 수 있다. (당연히 답을 도출 할 때에는 다시 부호를 바꾸어 주어야 한다.)
* 이 문제와는 관련이 없지만, 만약에 점수만을 최대화 하는 조건이라고 한다면 61번줄에 주석 친 부분을 사용하게 되는데, 이 경우에는 꼭 최대로 유량을 흘리지는 않지만, 코스트는 무조건 최대치까지 도달 할 수 있게된다.
소스 코드
'BOJ' 카테고리의 다른 글
1937] 욕심쟁이 판다 (0) | 2016.10.14 |
---|---|
2306] 유전자 (0) | 2016.09.25 |
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
1941] 소문난 칠공주 (0) | 2016.08.14 |
1052] 물병 (0) | 2016.07.22 |
설정
트랙백
댓글
글
문제 설명
: Description 그대로다. n개의 원소가 있고, [L,R]의 쿼리가 들어올 때마다
부분 배열의 힘을 구하는것이다.
여기서 라 하면 자연수 s의 개수를 뜻하는데, 부분 배열에서 이 모든 자연수 s에 대해
*
* s
를 구하는 문제이다.
일단 당연한 것은 모든 Query에 대해서 다 훑어보는 식으론 절대 못푼다는 것이다. (의 시간 복잡도를 가지기 때문)
여기서 유용한 것이 Sqrt decomposition (평방분할)을 이용하는 것이다. 평방분할이라는 것은 간단하게 N개의 집합을 sqrt(N)개의 집합으로 나누어 값을 다룬다고 생각하면 되는데,이 문제에서는 Query에 이것을 적용하는 Query Sqrt Decomposition을 이용할 것이다.
query에 대해서 분할하는 것을 Mo's Algorithm이라고도 하는 것 같은데 각각의 query [L,R] 에 대해서 L/sqrt(N)으로 정렬을 한다. (같을 경우 R에 대해서 정렬, 다르게 보자면, (L/sqrt(N))*sqrt(N) + R/sqrt(N) 이라는 value로 오름차순 정렬을 한다고 보면 된다.)
물론, 정렬을 하게 되면 query의 순서가 뒤바뀌기 때문에 따로 index를 저장 해주어야 하고,값을 변경하는 query가 존재하는 경우 적용 할 수 없는 것 같다.
대신, 구간의 특정 수의 개수라던가 하는 특수한 형태의 문제에는 아주 잘 적용되는 것 같다.
결론적으로, N개의 원소가 존재하고 query [L,R]이 존재할때, L/sqrt(N)과 R 우선순위로 정렬을 하게 된다면
1. N/sqrt(N) = sqrt(N)개의 집합(이제 Block이라고 하겠다)이 형성된다.
2. 하나의 Block 내에서 query [L,R] -> [L',R']의 변화가 있다고 하면, L'-L <= sqrt(N) 이고 R<=R' 이다. (즉, 같은 Block에서의 L/sqrt(N) 값은 동일하다)
3. 동일 Block 내에서의 R의 변화는 최대 N까지이므로, 최종적으로 모든 query에서의 R은 시간 복잡도 내에 변화한다.
4. 한 Block 내에서의 L의 range는 sqrt(N)이므로 (L/sqrt(N) 에 대해서 정렬을 해서 집합으로 묶어놨으니 당연한 것이다) 최종적으로 모든 query에 대해서 L은 시간 복잡도 내에서 변화한다.
5. 그렇기 때문에 Mo's algorithm은 의 시간 복잡도를 갖는다. (F는 L,R의 변화 할 때마다 값을 처리해주는 함수를 만들었을때, 그 함수의 처리 시간이다.)
그렇기 때문에 구간의 합 구하기, 최대값 구하기 같은 유형의 문제들을 굳이 segment tree나 fenwick tree를 구현하지 않더라도 최초의 [L,R]을 설정해 놓고 정렬된 query를 쭉 훑으면서 [L,R] -> [L',R']로의 query range를 확장, 축소 해나가면 해결이 가능하다.
더 자세한 내용은 링크를 통해 보는 게 좋겠다.
http://www.geeksforgeeks.org/mos-algorithm-query-square-root-decomposition-set-1-introduction/
https://www.hackerearth.com/notes/mos-algorithm/소스 코드
'BOJ' 카테고리의 다른 글
2306] 유전자 (0) | 2016.09.25 |
---|---|
8992] 집기 게임(Pickup Game) (1) | 2016.09.21 |
1941] 소문난 칠공주 (0) | 2016.08.14 |
1052] 물병 (0) | 2016.07.22 |
1328] 고층 빌딩 , 8895] 막대 배치 (0) | 2016.05.07 |
설정
트랙백
댓글
글
문제 설명
: 5x5 배열에서 길이가 7 경로 중 'S'를 4개 이상 포함한 경로의 개수를 구하는 문제.
단순히 dfs처럼 보이지만, 십자가 모양의 경로 같은 경우는 dfs로 구현해내기가 어렵다. (사실 잘 모르겠다)
5x5 배열이기 때문에 (0,0)..... (4,4)를 각각 출발점으로 삼는 경로를 모두 만들어내어 'S'가 4개 이상인 경우만 체크해주면 쉽게 해결이 된다.
현재 경로를 저장하는 stat과 1<<i 와의 &연산으로 인접한 경로로만 갈 수 있도록 한다.
소스 코드
'BOJ' 카테고리의 다른 글
8992] 집기 게임(Pickup Game) (1) | 2016.09.21 |
---|---|
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
1052] 물병 (0) | 2016.07.22 |
1328] 고층 빌딩 , 8895] 막대 배치 (0) | 2016.05.07 |
1007] Vector Matching (0) | 2016.01.01 |
설정
트랙백
댓글
글
문제 설명
: 최초 1리터가 담긴 물병들이 N개가 있을때, K개 이하로만 물이 들어있는 병을 만들고자 한다.
이때 같은 양의 물이 담겼을때만 물을 옮길 수 있다. 그렇다면 최소한으로 필요한 물병 구입 개수는?
문제 이해를 예시로 돕자면, N = 8 일때는 1 1 1 1 1 1 1 1 -> 2 2 2 2 -> 4 4 -> 8 로 계속 합칠 수 있으므로 답은 0.
N = 7, K= 1 일때는 1 1 1 1 1 1 1 -> .... -> 4 2 1 로, 1짜리 물병을 하나 더 구입해야 4 2 1 1 -> 4 2 2 -> 4 4 -> 8이 가능해진다.
핵심은 이진법에 있다. N을 이진수로 나타냈을 때, 1의 개수가 물이 들어있는 물병의 개수다.
N=13, K=1인 경우를 말해보자면, N = 1101(2)이고 8L 짜리 물병, 4L 짜리 물병, 1L 물병으로 나타낼 수 있다는 것이다.
여기에서 1L 짜리 물병을 추가하면? 1110 이 되는 것이고 이것은 8L , 4L, 2L 물병으로 나타낼 수 있다.
여기에 2L 물병을 추가하면 10000 이 되는것이고 16L 물병 하나로 k=1을 만족하게 된다.
즉, 1101 -> 1110 -> 10000 가 되려면 총 1+2 = 3 개의 물병이 필요하고, 이러한 연산은 n & -n 으로 가능하다.
(펜윅트리에서 구간 합을 구할때 사용하는 비트연산 방식과 동일하다)
소스 코드
'BOJ' 카테고리의 다른 글
8462] 배열의 힘 & Mo's Algorithm (0) | 2016.08.20 |
---|---|
1941] 소문난 칠공주 (0) | 2016.08.14 |
1328] 고층 빌딩 , 8895] 막대 배치 (0) | 2016.05.07 |
1007] Vector Matching (0) | 2016.01.01 |
1707] 이분 그래프 (0) | 2016.01.01 |
설정
트랙백
댓글
글
문제 설명
: 길이가 1,2.....N인 N개의 빌딩(막대)을 왼쪽에서는 L개, 오른쪽에서는 R개 보이도록 놓는 문제이다.
간단한 DP문제이다. 먼저 상태공간을 잡는 것이 중요한데, dp[i][l][r] 이라 하면 i번째 막대를 놓았을때
왼쪽에서 l개가 보이고 오른쪽에서 r개가 보이는 경우의 수이다.
먼저 1개를 놓아서 왼쪽,오른쪽 둘다 1개씩 보이는 경우와 2개를 놓았는데 왼쪽에 2개 오른쪽에 1개가 보이거나 왼쪽에 1개 오른쪽에 2개가 보이는 경우는 모두 1가지씩 이므로 dp[1][1][1] = dp[2][2][1] = dp[2][1][2] = 1 이다.
빌딩(막대)을 큰 것부터 즉, 내림차순으로 놓는다고 하면 i-1개를 다 놓고 나서 i번째에 왼쪽에 1개를 놓게되면
왼쪽에서는 1개가 더 보이게 되고, 오른쪽에서는 그대로 보이게 된다.
즉, dp[i][l][r] += dp[i-1][l-1][r] 이고, 오른쪽에 대해서도 마찬가지로 dp[i][l][r] += dp[i-1][l][r-1] 이다.
중요한것은 사이사이에 넣는 경우인데, 내림차순으로 놓는다면 사이에 넣는 경우에 왼쪽이나 오른쪽에서 보이는
개수는 그대로이기 때문에 ( 예를들어 5 4 가 있는데 5 3 4 처럼 3을 가운데에 넣는다면 여전히 왼쪽, 오른쪽에서는 한개씩 보인다) i개가 놓여져 있다면, 사이사이에는 i-2 경우의 수만큼 넣을 수 있다.
즉, 마지막으로 dp[i][l][r] += dp[i-1][l][r] * (i-2).
연산마다 모드를 취해주면 쉽게 답을 얻을 수 있다.
소스 코드
'BOJ' 카테고리의 다른 글
1941] 소문난 칠공주 (0) | 2016.08.14 |
---|---|
1052] 물병 (0) | 2016.07.22 |
1007] Vector Matching (0) | 2016.01.01 |
1707] 이분 그래프 (0) | 2016.01.01 |
1238] Silver Cow Party (파티) (0) | 2015.12.30 |
설정
트랙백
댓글
글
문제 설명
: 짝수 N개로 이루어진 점들을 각각 두개씩 짝지어서, 벡터의 합의 길이가 최소가 되도록 하는 문제.
점 A(x1,y1)와 B(x2,y2)가 존재한다면 A->B 벡터 성분은 (x2-x1,y2-y1) 이다.
이때 벡터의 길이는 sqrt((x2-x1)^2+(y2-y1)^2) 가 될것이다.
N자체는 20이하의 자연수이기 때문에 dfs로 간단하게 해결이 가능하다.
N/2 만큼의 점은 +성분을 가지고, 나머지 N/2 개의 점은 반대로 -성분을 가지는 것이기 때문에
해당 점마다 +,- 상태를 가지고 가지치기를 하면서 + 혹은 - 개수가 N/2에 도달 했을때, min값을 갱신하면 된다.
소스 코드
'BOJ' 카테고리의 다른 글
1052] 물병 (0) | 2016.07.22 |
---|---|
1328] 고층 빌딩 , 8895] 막대 배치 (0) | 2016.05.07 |
1707] 이분 그래프 (0) | 2016.01.01 |
1238] Silver Cow Party (파티) (0) | 2015.12.30 |
2188] 축사 배정 (0) | 2015.11.20 |
RECENT COMMENT