본문 바로가기

ps(알고리즘)

(44)
공항 이것도 그리디적인 해결 방법이 들어가는데, 1~g(i)번째 게이트중 하나에 도킹해야 한다면, g(i)부터 보면서 갈 수 있는 게이트 중최대한 큰 번호의 게이트에 도킹해야 한다.그런데 이걸 그냥 단순 for문으로 구현하면, 최대 g(i)번 탐색을 해야 하니까 시간복잡도가 GP가 되기 때문에 안된다.따라서 도킹을 하면 했다고 체크를 하고, 번호를 탐색하면서 최대 번호를 찾는 방식 말고 다른 방식을 사용해야 한다.g(i)가 들어왔을 때 결국 1~g(i)중 남아있는 번호의 최대를 구해야 한다. 이를 잘 생각해보면 한가지 알고리즘이 떠오른다.세그먼트 트리를 이용하면, 구간별로 max값을 쉽게 탐색할 수도 있고 update도 빠르게 할 수 있다.#include#includeusing namespace std;int..
빵집 dfs와 그리디 알고리즘이 합쳐진 문제이다.왼쪽에서 오른쪽으로 이동을 하는데 왼쪽의 R개의 점에 대해서 다 탐색을 해봐야 한다.여기서 그리디를 적용해야 하는데 길이 겹치면 안되기 때문에 길 하나를 찾아도 최대한 나머지 길들에 영향을 주지 않아야 한다.즉, 위에서부터 (1,1)부터 (R,1)까지 R번의 dfs를 도는데 최대한 위로 가야 아래쪽에서 영향을 안 받는다.오른쪽 위, 오른쪽, 오른쪽 아래 순으로 탐색을 해 나가면 된다.int main(){ scanf("%d %d",&R,&C); for(int i=1;iarr 배열 안에 건물의 상태를 담고, dfs를 왼쪽 시작점들에 대해서 탐색한다.int path[504];int wx[3]={-1,0,1},wy[3]={1,1,1};bool dfs(int ..
저울 저울들을 합쳐서 만들 수 없는 무게를 구하면 된다.간단하게 풀 수 있는데 그냥 무게들을 정렬해 놓고 작은 것부터 더해 나가다가 다음 무게가 이전까지의 모든 무게의 합보다 커버리면 무게의 합+1부터는 만들 수 없다고 판단하면 된다.좀 더 자세히 설명해보자면, 작은것부터 큰것까지 무게들을 정렬했을 때 1번째부터 n번째 무게까지의 합을 sum_n이라고 하자.그리고 1,2,3,...., sum_n은 전부 다 만들 수 있다고 가정하자.이 때 sum_n보다 n+1번째 무게가 작다면, sum_n과 n+1번째 무게의 합 즉, 1부터 sum_(n+1) 까지도 전부 다 만들 수 있다.(1,2,3,..., sum_n을 만들 수 있다고 가정했기 때문에 n+1번째 무게에 1,2,..., sum_n을 더하면 되기 때문)만약 su..
친구 네트워크 친구 관계가 추가될 때마다 그룹에 몇 명이 있는지 출력해야 하기 때문에 그룹에 몇 명이 있는지 탐색하는 과정을 F번 반복해야 한다.일일이 다 친구들과의 관계를 탐색하는 식으로 하면 시간 복잡도가 최소 F제곱이어서 불가능하다. union-find 알고리즘을 쓰면 이를 해결할 수 있다.#include#include#includeusing namespace std;map friends;int group[300004];int gsize[300004];int fin(int x){ if(x==group[x]) return x; return fin(group[x]);}int uni(int a, int b){ int ga = fin(a); int gb = fin(b); if(ga != gb)..
피보나치 수 6 그냥 n번째 피보나치 수를 구하는 문제인데 값이 커서 최적화를 잘 시켜야 한다.그냥 이 행렬 곱을 이용해서 구하면 된다.행렬의 n제곱을 계산하면 되는데 분할정복 느낌?으로 n/2제곱을 계산하는 식으로 재귀함수를 거치면log(n)의 시간만에 구할 수 있어서 빠르다.#includelong long N;long long K = 1000000007;long long dp[2][2];void fibo(long long n){ if(n==1) return; long long m = n/2; fibo(m); long long mm[2][2]; mm[0][0] = dp[0][0]*dp[0][0]%K + dp[0][1]*dp[1][0]%K; mm[0][1] = dp[0][0]*dp[0][..
문제집 먼저 푸는 것이 없는 문제를 풀 수 있고, 쉬운 문제부터 풀어야 하기 때문에 먼저 푸는 것이 없는 문제들을 우선 순위 큐에 넣고 최소값을 top으로 구해서 출력하면 된다.그리고 문제를 썼으면 pop을 하면서 해당 문제로 인해 먼저 푸는 것이 없어지는 문제들을 큐에 넣어주면 되는 간단한 문제이다.#include#include#include#includeusing namespace std;vector prob[40004];vector rev[40004];priority_queuelast;int N,M;int main(){ scanf("%d %d",&N,&M); for(int i=1;i해결 코드이다.
보석 도둑 간단한 문제이다.그리디 알고리즘을 쓰면 된다.최대 무게가 작은 가방부터 보면서 담을 수 있는 보석 중에 가격이 젤 높은 보석을 담으면 된다.가방 개수가 K개인데 가방마다 보석 N개를 전부 조사하면 O(NK)로 시간이 너무 오래 걸리니까보석도 무게가 작은거부터 스택에 넣어두고 스택을 유지하면서 top을 담으면 된다.#include#include#includeusing namespace std;int N,K;long long bag[400005];struct Data{ long long m,v; bool operator values;int main(){ scanf("%d %d",&N,&K); for(int i=1;i코드이다. 계속 런타임 에러가 생겨서 맞왜틀 고쳤는데 에러 발생 이유는 ..
후위 표기식 후위 표기식은 꽤 유명한 문제인데 스택을 사용해야 한다.기호는 +,-,*,/,(,)만 등장한다.문제를 풀기 위한 스텝을 보면일단 문자 A,B같은게 나오면 그냥 출력한다.기호가 나오면 스택에 넣는데 넣기 전에 자기보다 우선순위가 높은 것들을 출력해야 한다.+,-는 자기보다 먼저 등장한 +나 -, 그리고 *,/가 전부 다 우선순위가 높기 때문에 (가 나오기 전까지 다 출력해야 한다.if(eq[i]=='+' || eq[i]=='-'){ while(!st.empty()){ if(st.top()=='(') break; printf("%c",st.top()); st.pop(); } st.push(eq[i]);}*,/는 자기보다 먼저 등장한 *,/만 출력하면 된다..