www.acmicpc.net/problem/2075

 

2075번: N번째 큰 수

첫째 줄에 N(1 ≤ N ≤ 1,500)이 주어진다. 다음 N개의 줄에는 각 줄마다 N개의 수가 주어진다. 표에 적힌 수는 -10억보다 크거나 같고, 10억보다 작거나 같은 정수이다.

www.acmicpc.net

 

 

[난이도] Gold4

[유형] 우선순위큐

 

[풀이]

메모리 제한이 12MB으로 적으므로 우선순위 큐를 이용해서 푼다.
큐의 크기가 N 이하이면 무조건 push,
아닌 경우 top보다 작은 것들은 무시, top보다 크면 pop하고 push한다
모든 수를 다 봤을 때 top이 정답이다.

 

#include <cstdio>
#include <queue>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;
int N;
int main(){
    priority_queue<int,vector<int>,greater<int>> a;
    scanf("%d",&N);
    for(int i=0;i<N*N;i++) {
        int v;
        scanf("%d",&v);
        if(a.size()<N) a.push(v);
        else if(a.top() < v) {
            a.pop();
            a.push(v);
        }
    }
    printf("%d",a.top());
}

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/2075.cpp

 

www.acmicpc.net/problem/2056

 

2056번: 작업

수행해야 할 작업 N개 (3 ≤ N ≤ 10000)가 있다. 각각의 작업마다 걸리는 시간(1 ≤ 시간 ≤ 100)이 정수로 주어진다. 몇몇 작업들 사이에는 선행 관계라는 게 있어서, 어떤 작업을 수행하기 위해

www.acmicpc.net

 

 

[난이도] Gold4

[유형] 위상정렬

 

[풀이]

위상정렬로 각 작업을 방문하면서 total 배열에 그 작업에 도착하기 까지의 시간을 기록하면 된다.

#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
int N,work[10001],total[10001],in[10001],ret;
vector<int> adj[10001];
int main(){
    scanf("%d",&N);
    for(int i=1;i<=N;i++){
        int ac,pre;
        scanf("%d%d",&work[i],&ac);
        in[i] = ac;
        for(int j=0;j<ac;j++){
            scanf("%d",&pre);
            adj[pre].push_back(i);
        }
    }
    queue<int> q;
    for(int i=1;i<=N;i++) if(!in[i]) q.push(i);
    while(!q.empty()){
        int qf = q.front(); q.pop();
        ret = max(ret,total[qf]+work[qf]);
        for(auto nxt : adj[qf]){
            total[nxt] = max(total[nxt],total[qf]+work[qf]);
            if(--in[nxt]==0) q.push(nxt);
        }

    }   
    printf("%d",ret);
}

 

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/2056.cpp

www.acmicpc.net/problem/1976

 

1976번: 여행 가자

동혁이는 친구들과 함께 여행을 가려고 한다. 한국에는 도시가 N개 있고 임의의 두 도시 사이에 길이 있을 수도, 없을 수도 있다. 동혁이의 여행 일정이 주어졌을 때, 이 여행 경로가 가능한 것인

www.acmicpc.net

 

 

[난이도] Gold4

[유형] DFS

 

[풀이]

여행해야하는 임의의 한 점에서 DFS를 돌았을 때 여행 경로에 있는 모든 점을 Visit한 경우에만 YES이다.

 

 

#include <cstdio>
using namespace std;
int N,M,d[1001];
bool adj[201][201],visit[201];
void dfs(int n){
    visit[n] = 1;
    for(int i=1;i<=N;i++)
        if(adj[n][i] && !visit[i]) dfs(i);
}
int main(){
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++) scanf("%d",&adj[i][j]);
    for(int i=0;i<M;i++) scanf("%d",&d[i]);
    dfs(d[0]);
    for(int i=0;i<M;i++) {
        if(!visit[d[i]]) {
            puts("NO");
            return 0;
        }
    }
    puts("YES");
}

 

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/1976.cpp

www.acmicpc.net/problem/1967

 

1967번: 트리의 지름

파일의 첫 번째 줄은 노드의 개수 n(1 ≤ n ≤ 10,000)이다. 둘째 줄부터 n-1개의 줄에 각 간선에 대한 정보가 들어온다. 간선에 대한 정보는 세 개의 정수로 이루어져 있다. 첫 번째 정수는 간선이 연

www.acmicpc.net

 

 

[난이도] Gold4

[유형] 트리의 지름(DFS)

 

[풀이] 

트리의 지름 : 트리에서 거리가 가장 먼 두 점 사이의 거리. 구

하는 방법 : 임의의 점에서 DFS로 가장 먼 점을 찾은 뒤에 그 점에서 DFS를 이용해서 가장 먼 점을 찾으면 그 거리가 트리의 지름이 된다.

 

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
int N,ans,mxN,mxV;
bool visit[10001];
vector<pair<int,int>> adj[10001];
void dfs(int n,int c){
    visit[n] = 1;
    if(c>mxV){
        mxV=c;
        mxN=n;
    }
    for(auto nxt : adj[n]){
        if(!visit[nxt.first]) dfs(nxt.first,c+nxt.second);
    }
}
int main(){
    scanf("%d",&N);
    for(int i=0;i<N-1;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        adj[a].push_back({b,c});
        adj[b].push_back({a,c});
    }
    dfs(1,0);
    memset(visit,0,sizeof(visit));
    mxV=0;
    dfs(mxN,0);
    printf("%d",mxV);
}

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/1967.cpp

 

www.acmicpc.net/problem/19238

 

19238번: 스타트 택시

첫 줄에 N, M, 그리고 초기 연료의 양이 주어진다. (2 ≤ N ≤ 20, 1 ≤ M ≤ N2, 1 ≤ 초기 연료 ≤ 500,000) 연료는 무한히 많이 담을 수 있기 때문에, 초기 연료의 양을 넘어서 충전될 수도 있다. 다

www.acmicpc.net

 

 

[난이도] Gold4

[유형] BFS, Simulation (삼성SW기출)

 

[풀이] 

1. y시작,x시작,y종료,x종료,현재 택시위치에서의 거리 d 이 5가지를 저장하는
구조체 P를 정의한다.
2. vector<P> s를 정의 M개의 P를 저장한다.
3. M회 루프를 돌면서 매 시행마다 s를 정렬해준다. 정렬은 comparator 를
   재정의하는 방식으로 한다. 거리,y좌표,x 우선순위로 정렬하면 항상
   s[0]이 지금 태우러 가야하는 사람이다. 뽑은 뒤 s[0]은 필요없으므로
   벡터에서 지워준다.
4. 벽에 의해 택시로 도달할 수 없는 사람이 있는 겨우와, 연료를 다쓰는 경우를
   예외처리 해준다.

 

#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
struct P{
    int y,x,ey,ex,d;
};
vector<P> s;
int dy[4] = {-1,1,0,0};
int dx[4] = {0,0,1,-1};
int N,M,K,map[21][21],py,px,INF=9e8;
bool visit[21][21];
int bfs(int y,int x){
    memset(visit,0,sizeof(visit));
    queue<P> q;
    q.push({y,x});
    visit[y][x] = 1;
    int ret = 0;
    while(!q.empty()){
        int sz = q.size();
        while(sz--){
            P qf = q.front(); q.pop();
            if(qf.y==py&&qf.x==px) return ret;
            for(int i=0;i<4;i++){
                int ny = qf.y+dy[i];
                int nx = qf.x+dx[i];
                if(ny < 1 || nx < 1 || ny > N || nx > N || map[ny][nx]) continue;
                if(!visit[ny][nx]){
                    q.push({ny,nx});
                    visit[ny][nx] = 1;
                }
            }
        }
        ret++;
    }
    return INF;
}
bool cmp(P& a,P& b){
    if(a.d < b.d) return 1;
    else if(a.d==b.d){
        if(a.y<b.y) return 1;
        else if(a.y==b.y) return a.x < b.x;
        return 0;
    }
    return 0;
}
int main(){
    scanf("%d%d%d",&N,&M,&K);
    s.resize(M);
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++) scanf("%d",&map[i][j]);
    
    scanf("%d%d",&py,&px);
    for(int i=0;i<M;i++) scanf("%d%d%d%d",&s[i].y,&s[i].x,&s[i].ey,&s[i].ex);

    for(int i=0;i<M;i++){
        for(int j=0;j<s.size();j++) s[j].d = bfs(s[j].y,s[j].x);    
        sort(s.begin(),s.end(),cmp);
        P t = s[0];
        s.erase(s.begin());
        if(K-t.d < 0) {
            K=-1;
            break;
        }
        K-=t.d, py=t.y, px=t.x;

        int nDist = bfs(t.ey,t.ex);
        if(K-nDist < 0){
            K=-1;
            break;
        }
        py=t.ey, px=t.ex;
        K+=nDist;
    }
    printf("%d",K);
}

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/19238.cpp

 

www.acmicpc.net/problem/1918

 

1918번: 후위 표기식

첫째 줄에 중위 표기식이 주어진다. 단 이 수식의 피연산자는 A~Z의 문자로 이루어지며 수식에서 한 번씩만 등장한다. 그리고 -A+B와 같이 -가 가장 앞에 오거나 AB와 같이 *가 생략되는 등의 수식

www.acmicpc.net

 

 

[난이도] Gold4

[유형] 스택 (중위표기법 -> 후위표기법)

 

[풀이] 스택 (중위표기법 -> 후위표기법)

연산자 우선순위와 Stack을 이용. 연산자의 우선순위는 ( < -,+ < /,* : )는 Stack에 들어가지 않으므로 정의하지 않는다. 문자열을 순회하면서

1. 피연산자면 바로 출력

2. '('이면 스택에 push

3. ')'이면 여는 괄호가 나올때까지 스택의 원소를 팝하면서 출력

4. Stack이 비어있거나 Stack의 top보다 우선순위가 낮아질때까지 Stack의 top을 pop하면서 출력 후 push ('('인 경우 2에서 예외로 무조건 push)

 

4번에서 while문을 통해 반복해주는 것이 중요.

 

#include <stack>
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
string a,ret;
int p(char c){
    if(c=='(') return 0;
    if(c=='+'||c=='-') return 1;
    return 2;
}
int main(){
    cin >> a;
    stack<char> s; 
    for(char c : a){
        if(isalpha(c)) ret+=c;
        else if(c=='(') s.push(c);
        else if(c==')'){
            while(1){
                char op = s.top(); s.pop();
                if(op=='(') break;
                ret+=op;
            }
        }
        else{
            while(!s.empty() && p(s.top()) >= p(c)) {
                ret+=s.top();
                s.pop();
            }
            s.push(c);
        }
    }
    while(!s.empty()) {
        ret+=s.top();
        s.pop();
    }
    cout << ret;
} 

 

github.com/has2/Problem-Solving/commit/f60ec108a19e4d6d59156a99880d7e222b1a3f26

www.acmicpc.net/problem/17779

 

17779번: 게리맨더링 2

재현시의 시장 구재현은 지난 몇 년간 게리맨더링을 통해서 자신의 당에게 유리하게 선거구를 획정했다. 견제할 권력이 없어진 구재현은 권력을 매우 부당하게 행사했고, 심지어는 시의 이름

www.acmicpc.net

 

 

[난이도] Gold4

[유형] Brute force, DFS (삼성SW기출)

 

[풀이]

1. 문제의 주어진 조건에 따라 5선거구의 경계를 체크한다.

2. (1,1)은 1선거구, (1,N)은 2선거구, (N,1)은 3선거구 (N,N)은 4선거구에 각각 무조건 포함되므로 4개의 점에서 DFS를 수행하면서 각 선거구의 인구를 구한다.

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int N,map[21][21],A[21][21],total,ans=1e8;
int dy[4] = {-1,1,0,0};
int dx[4] = {0,0,1,-1};
bool check(int d1,int d2,int x,int y){
    bool r = d1 >= 1 && d2 >= 1 && 1 <= x && x < x+d1+d2 && x+d1+d2 <= N;
    bool c = 1 <= y-d1 && y-d1 < y && y < y+d2 && y+d2 <=N;
    return r&&c;
}
void mask(int d1,int d2,int x,int y){
    int sx,sy,dx,dy;

    sx=x,sy=y,dx=1,dy=-1;
    for(int i=0;i<=d1;i++) {
        map[sx][sy] = 1;
        sx+=dx,sy+=dy;
    }
    sx=x,sy=y,dx=1,dy=1;
    for(int i=0;i<=d2;i++) {
        map[sx][sy] = 1;
        sx+=dx,sy+=dy;
    }
    sx=x+d1,sy=y-d1,dx=1,dy=1;
    for(int i=0;i<=d2;i++) {
        map[sx][sy] = 1;
        sx+=dx,sy+=dy;
    }  
    sx=x+d2,sy=y+d2,dx=1,dy=-1;
    for(int i=0;i<=d1;i++) {
        map[sx][sy] = 1;
        sx+=dx,sy+=dy;
    }     
}

int dfs(int d1,int d2,int x,int y,int r,int c,int k){
    if(k==1){
        if(!(1<=r&&r<x+d1&&1<=c&&c<=y)) return 0;
    }else if(k==2){
        if(!(1<=r&&r<=x+d2&&y<c&&c<=N)) return 0;
    }else if(k==3){
        if(!(x+d1<=r&&r<=N&&1<=c&&c<y-d1+d2)) return 0;
    }else if(k==4){
        if(!(x+d2<r&&r<=N&&y-d1+d2<=c&&c<=N)) return 0;
    }
    map[r][c] = k;
    int ret = A[r][c];
    for(int i=0;i<4;i++){
        int nr = r+dx[i];
        int nc = c+dy[i];
        if(nr < 1 || nc < 1 || nr > N || nc > N || map[nr][nc]) continue; 
        ret += dfs(d1,d2,x,y,nr,nc,k);
    }
    return ret;
}

int main(){
    scanf("%d",&N);
    for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++) {
            scanf("%d",&A[i][j]);
            total+=A[i][j];
        }

    for(int i=1;i<=N;i++){
        for(int j=1;j<=N;j++){
            for(int d1=1;d1<=N;d1++){
                for(int d2=1;d2<=N;d2++){
                    if(!check(d1,d2,i,j)) continue;
                    memset(map,0,sizeof(map));
                    mask(d1,d2,i,j);
                    int sx = 1,sy=1;
                    vector<int> sum;
                    sum.push_back(dfs(d1,d2,i,j,1,1,1));
                    sum.push_back(dfs(d1,d2,i,j,1,N,2));
                    sum.push_back(dfs(d1,d2,i,j,N,1,3));
                    sum.push_back(dfs(d1,d2,i,j,N,N,4));
                    int rm = total;
                    for(int i=0;i<4;i++) rm -= sum[i];
                    sum.push_back(rm);
                    sort(sum.begin(),sum.end());
                    ans = min(ans,sum.back()-sum.front());
                }
            }
        }
    }    
    printf("%d",ans);
}

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/17779.cpp

 

www.acmicpc.net/problem/17406

 

17406번: 배열 돌리기 4

크기가 N×M 크기인 배열 A가 있을때, 배열 A의 값은 각 행에 있는 모든 수의 합 중 최솟값을 의미한다. 배열 A가 아래와 같은 경우 1행의 합은 6, 2행의 합은 4, 3행의 합은 15이다. 따라서, 배열 A의

www.acmicpc.net

 

 

[난이도] Gold4

[유형] 시뮬레이션

 

[풀이]

next_permutation을 이용해 모든 경우의 수를 다해본다. permutation으로 돌아가는것은 index라는 것에 주의.

#include <cstdio>
#include <algorithm>
using namespace std;
int N,M,K,org[51][51],cp[51][51],tmp[51][51],r[6],c[6],s[6],v[6],inf=1e8;
int sol(){
    int ret = inf;
    for(int i=0;i<K;i++){
        int ll = 2*s[v[i]]+1, yy = r[v[i]]-s[v[i]], xx = c[v[i]]-s[v[i]];        
        int l = ll, y = yy, x = xx;
        while(l>0){
            if(l==1) {
                tmp[y][x] = cp[y][x];
                break;
            }
            for(int j=x+1;j<x+l;j++) tmp[y][j] = cp[y][j-1];
            for(int j=y+1;j<y+l;j++) tmp[j][x+l-1] = cp[j-1][x+l-1];
            for(int j=x;j<x+l-1;j++) tmp[y+l-1][j] = cp[y+l-1][j+1];
            for(int j=y;j<y+l-1;j++) tmp[j][x] = cp[j+1][x];
            y++,x++;
            l-=2;
        }
        for(int j=yy;j<yy+ll;j++)
            for(int k=xx;k<xx+ll;k++) cp[j][k] = tmp[j][k];
    }
    for(int i=1;i<=N;i++){
        int sum = 0;
        for(int j=1;j<=M;j++) sum+=cp[i][j];
        ret = min(ret,sum);
    }
    return ret;
}
int main(){
    scanf("%d%d%d",&N,&M,&K);
    for(int i=1;i<=N;i++) 
        for(int j=1;j<=M;j++) scanf("%d",&org[i][j]);

    for(int i=0;i<K;i++) {
        scanf("%d%d%d",&r[i],&c[i],&s[i]);
        v[i] = i;
    }
    int ans = inf;
    do{
        for(int i=1;i<=N;i++) copy(org[i],org[i]+M+1,cp[i]);
        ans =min(ans,sol());
    }while(next_permutation(v,v+K));
    printf("%d",ans);
} 

 

github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold4/17406.cpp

+ Recent posts