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

 

1445번: 일요일 아침의 데이트

첫째 줄에 숲의 세로 크기 N과 가로 크기 M이 주어진다. N과 M은 3보다 크거나 같고, 50보다 작거나 같은 자연수이다. 둘째 줄부터 숲의 지도가 주어진다. 숲의 지도는 S, F, g, . 만으로 이루어져 있

www.acmicpc.net

 

 

[난이도] Gold2
[유형] 다익스트라

[풀이]
cost를 {쓰레기의 위치, 쓰레기에 인접한 위치}의 pair로 두고 다익스트라를 돌려주면 됩니다.

 

#include <cstdio>
#include <iostream>
#include <functional>
#include <queue>
#include <algorithm>
using namespace std;
struct P{
    pair<int,int> g,pos;
};
int N,M,dy[4]={-1,1,0,0},dx[4]={0,0,1,-1},sy,sx,ey,ex;
char board[50][50];
pair<int,int> dist[50][50];
struct cmp{
    bool operator()(P& a,P b){
        if(a.g.first>b.g.first) return true;
        else if(a.g.first==b.g.first) return a.g.second>b.g.second;
        return false;
    }
};
int main(){
    scanf("%d%d",&N,&M);
    for(int i=0;i<N;i++)
        for(int j=0;j<M;j++) {
            scanf(" %c",&board[i][j]);
            if(board[i][j]=='S') sy=i,sx=j;
            if(board[i][j]=='F') ey=i,ex=j;
            dist[i][j]={9e8,9e8};
        }
    priority_queue<P,vector<P>,cmp> pq;
    dist[sy][sx]={0,0};
    pq.push({{0,0},{sy,sx}});
    while(!pq.empty()){
        auto [g,pos] = pq.top(); pq.pop();
        auto [y,x] = pos;
        if(g!=dist[y][x]) continue;
        for(int i=0;i<4;i++){
            int ny=y+dy[i],nx=x+dx[i];
            if(ny<0||nx<0||ny>=N||nx>=M) continue;
            pair<int,int> p = g;
            if(board[ny][nx]=='g') p = {g.first+1,g.second};
            else if(board[ny][nx]=='.') {
                bool ok=0;
                for(int j=0;j<4;j++){
                    int ty=ny+dy[j],tx=nx+dx[j];
                    if(ty<0||tx<0||ty>=N||nx>=M) continue;
                    if(board[ty][tx]=='g'){
                        ok=1;
                        break;
                    }
                }
                if(ok) p = {g.first,g.second+1};
            }
            if(p<dist[ny][nx]){
                dist[ny][nx]=p;
                pq.push({p,{ny,nx}});
            }
        }
    }
    printf("%d %d",dist[ey][ex].first,dist[ey][ex].second);
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/1445.cpp


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

 

14725번: 개미굴

첫 번째 줄은 로봇 개미가 각 층을 따라 내려오면서 알게 된 먹이의 정보 개수 N개가 주어진다.  (1 ≤ N ≤ 1000) 두 번째 줄부터 N+1 번째 줄까지, 각 줄의 시작은 로봇 개미 한마리가 보내준 먹이

www.acmicpc.net

 


[난이도] Gold2
[유형] Trie

[풀이]
Trie 문제인데 정렬을 이용하여 간단히 풀 수 있습니다.
출력을 할 때, 먹이정보가 오름차순으로 빠른 순서인 개미의 정보부터 출력을 해야합니다.
예를 들어, A B C E 보다 A B C D 인 먹이정보를 가져온 개미의 정보부터 출력을 해야합니다.
각 개미의 먹이정보를 vector<string>에 넣은 뒤 정렬하면 vector의 comparator에 의해 저절로 오름차순으로
정렬이 되기 때문에
정렬 된 이후 0~N-1 번 개미의 먹이정보를 순차적으로 출력해주면 됩니다.

i-1번 개미 : A B C D
  i번 개미 : A B C E

먹이정보가 위와 같은 경우에는
i번 개미의 정보를 찍을 때, A,B,C는 이미 i-1번 개미의 정보를 찍을 때 찍은 E의 조상 노드이므로
출력을 하면 안됩니다.
이를 확인하기 위해 단순하게 i번 개미의 먹이정보를 출력하기 전에 i-1번 개미의 먹이정보가 비교해서
i-1,i가 같은 먹이 (위의 예시에서 A,B,C) 까지는 출력을 하지 않으면 됩니다.

 

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int N,K;
vector<string> v[1000]; 
string line(int k){
    string ret;
    while(k--) ret+="--";
    return ret;
}
int main(){
    cin >> N;
    for(int i=0;i<N;i++){
        vector<string> t;
        cin >> K;
        while(K--){
            string s;
            cin >> s;
            t.push_back(s);
        }
        v[i]=t;
    }
    sort(v,v+N);
    for(int i=0;i<N;i++){
        int d=0;
        if(i!=0){
            for(int j=0;j<v[i].size()&&j<v[i-1].size();j++){
                if(v[i][j]==v[i-1][j]) d++;
                else break;
            }
        }
        for(int j=d;j<v[i].size();j++) cout << line(j)+v[i][j] << '\n';
    }
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/14725.cpp

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

 

9997번: 폰트

첫째 줄에 단어의 개수 N (1 ≤ N ≤ 25)가 주어진다. 다음 N개 줄에는 사전에 포함되어있는 단어가 주어진다. 단어의 길이는 100을 넘지 않으며, 중복되는 단어는 주어지지 않는다.

www.acmicpc.net

 

 

 

[난이도] Gold2
[유형] 비트마스크

[풀이]
주어지는 단어에 포함된 알파벳을 26자리 비트 int로 변환이 가능합니다.
int로 변환을 해준 뒤에 재귀를 이용해서 만들 수 있는 경우의 수를 모두 조합해주면 됩니다.
현재 단어를 포함 시킬때는 비트or 연산을 이용해 O(1)에 연산이 가능합니다.

 

#include <iostream>
#include <string>
using namespace std;
int N,ans,a[25];
void sol(int n,int b){
    if(n==N) {
        if(b==(1<<26)-1) ans++;
        return;
    }
    sol(n+1,b);
    sol(n+1,b|a[n]);
}
int main(){
    cin >> N;
    for(int i=0;i<N;i++) {
        string s;
        cin >> s;
        int b=0;
        for(auto c : s) b |= (1<<(c-'a'));
        a[i]=b;
    }
    sol(0,0);
    cout << ans;
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/9997.cpp

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

 

2159번: 케익 배달

첫째 줄에 N이 주어지고 둘째 줄에는 선아가 일하는 레스토랑의 위치가, 셋째 줄부터는 N명의 위치가 X와 Y로 주어진다. 두 좌표 사이에는 공백이 하나 이상 있다. (1 ≤ N, X, Y ≤ 100,000)

www.acmicpc.net

 

 

[난이도] Gold2
[유형] 다익스트라

[풀이]
고객의 위치와 고객의 위치에서 상하좌우 인접 격자를 노드로 만든 뒤,
다익스트라를 돌리면 됩니다.

 

#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <functional>
#include <queue>
using namespace std;
using ll = long long;
struct P{
    int u,v,d;
};
int N,dy[4]={-1,1,0,0},dx[4]={0,0,1,-1},id;
ll dist[800001];
vector<P> a[100001];
vector<pair<ll,int>> adj[800001];
bool inRange(int y,int x){
    return y>=0&&x>=0&&y<=100000&&x<=100000;
}
int main(){
    scanf("%d",&N);
    N++;
    for(int i=0;i<N;i++) {
        int y,x;
        scanf("%d%d",&y,&x);
        a[i].push_back({y,x,id++});
        if(i==0) continue;
        for(int k=0;k<4;k++){
            int ny=y+dy[k],nx=x+dx[k];
            if(inRange(ny,nx)) a[i].push_back({ny,nx,id++});
        }
    }
    for(int i=1;i<N;i++){
        for(int j=0;j<a[i-1].size();j++){
            for(int k=0;k<a[i].size();k++){
                int d = abs(a[i-1][j].u-a[i][k].u)+abs(a[i-1][j].v-a[i][k].v);
                adj[a[i-1][j].d].push_back({a[i][k].d,d});
            }
        }
    }
    priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<pair<ll,int>>> pq;
    pq.push({0,0});
    for(int i=0;i<id;i++) dist[i]=9e15;
    dist[0]=0;

    while(!pq.empty()){
        auto [d,cur] = pq.top(); pq.pop();
        if(dist[cur]!=d) continue;
        for(auto [nxt,cost] : adj[cur]){
            if(d+cost < dist[nxt]){
                dist[nxt]=d+cost;
                pq.push({dist[nxt],nxt});
            }
        }
    }
    ll ans=9e15;
    for(auto [u,v,id] : a[N-1]) ans=min(ans,dist[id]);
    printf("%lld",ans);
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/2159.cpp

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

 

1818번: 책정리

동혁이는 캠프가 끝나고 집에 가서 책꽂이 정리를 하고 있었다. 책들은 한 줄로 길게 꽂히 있었다. 동혁이의 책은 1번부터 N번까지 숫자로 표현되고  현재 뒤죽박죽 되어있는 순서를 왼쪽부터

www.acmicpc.net

 

 

[난이도] Gold2
[유형] DP

[풀이]
오름차순으로 되어있는 최대 길이 수열을 구한 뒤 이 값을 N에서 빼주면 됩니다.
이게 가능한 이유는
오름차순으로 되어있는 수들은 건드릴 필요가 없고,
오름차순으로 되어있지 않은 나머지 수들은 최소 한번씩은 움직여야 하기 때문입니다.

 

오름차순으로 되어있는 최대 길이 수열은 결국 유명한 증가하는 최대 부분 수열(LIS) 입니다.

이것은 DP로 구할 수 있습니다. N이 20만이기 때문에 O(NlogN) 알고리즘을 사용해서 구해주면 됩니다. 

 

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int N,a[200000];
vector<int> v;
int main(){
    scanf("%d",&N);
    for(int i=0;i<N;i++) scanf("%d",&a[i]);
    v.push_back(a[0]);
    for(int i=1;i<N;i++){
        auto idx = lower_bound(v.begin(),v.end(),a[i])-v.begin();
        if(idx<v.size()) v[idx]=a[i];
        else v.push_back(a[i]);
    }
    printf("%d",N-v.size());
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/1818.cpp

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

 

2879번: 코딩은 예쁘게

첫째 줄에 줄의 개수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 현재 줄에 있는 탭의 개수가 주어지며, 1번째 줄부터 순서대로 주어진다. 탭의 개수는 0보다 크거나 같고, 80보다 작거나 같은 정수

www.acmicpc.net

 

 

[난이도] Gold2
[유형] Greedy

[풀이]
우선 배열에 현재 (현재 탭 개수 - 목표 탭 개수) 를 저장해줍니다.
배열에서 양수인 것들은 탭을 빼줘야 하는 것들이고
음수인 것들은 탭을 더해주야 하는 것들입니다.

잘 생각해보면 부호가 같은 연속된 수열에서 절댓값이 가장 작은 값만큼 탭을 제거하거나 추가하는
연산을 하는게 가장 효율적인 연산입니다.

전체 수열이 0이 될때까지 루프를 돌면서 수열 전체를 확인하면서 위의 방법으로 탭을 추가하거나 제거해주면 됩니다.

 

#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
int N,a[1001];
int main(){
    scanf("%d",&N);
    for(int i=0;i<N;i++) scanf("%d",&a[i]);
    for(int i=0;i<N;i++) {
        int v;
        scanf("%d",&v);
        a[i]-=v;
    }
    int ans=0;
    bool ok=1;
    while(ok){
        ok=0;
        for(int i=0;i<N;i++){
            if(!a[i]) continue;
            ok=1;
            int minv=a[i];
            for(int j=i+1;j<=N;j++){
                if(a[i]*a[j]>0){
                    if(abs(a[j])<abs(minv)){
                        minv=a[j];
                    }
                }else{
                    ans+=abs(minv);
                    for(int k=i;k<j;k++) a[k]-=minv;     
                    i=j-1;
                    break;
                }
            }
        }
    }
    printf("%d",ans);
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/2879.cpp

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

 

2307번: 도로검문

그림 1은 어떤 도시의 주요 지점과 그 지점들 간의 이동시간을 나타낸 그래프이다. 그래프의 노드는 주요 지점을 나타내고  두 지점을 연결한 도로(에지)에 표시된 수는 그 도로로 이동할 때 걸

www.acmicpc.net

 

 

[난이도] Gold2
[유형] 다익스트라

[풀이]
간선을 하나씩 제거해보며 다익스트라를 돌려보면 900ms 대로 아슬아슬하게 AC를 받을 수 있습니다.
최단거리에 포함된 간선만 제거해보는 방식으로 최적화를 하면 훨씬 빠른 시간내에 AC를 받을 수 있습니다.

 

 

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#include <functional>
using namespace std;
int N,M,dist[1001];
vector<pair<int,int>> adj[1001],path;
int dijk(int a,int b){
    for(int i=1;i<=N;i++) dist[i]=9e8;
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq;
    dist[1]=0;
    pq.push({0,1});
    while(!pq.empty()){
        auto [d,cur] = pq.top(); pq.pop();
        if(dist[cur]!=d) continue;
        for(auto [nxt,cost] : adj[cur]){
            if((cur==a&&nxt==b)||(cur==b&&nxt==b)){
                cost = 9e8;
            }
            if(dist[nxt]>d+cost){
                dist[nxt]=d+cost;
                pq.push({dist[nxt],nxt});
            }
        }
    }
    return dist[N];
}
int main(){
    scanf("%d%d",&N,&M);
    while(M--){
        int a,b,t;
        scanf("%d%d%d",&a,&b,&t);
        adj[a].push_back({b,t});
        adj[b].push_back({a,t});
        path.push_back({a,b});
    }  
    int ans=0;
    for(auto [a,b] : path) ans=max(dijk(a,b),ans);
    if(ans>=9e8) {
        puts("-1");
        return 0;
    }
    printf("%d",ans-dijk(0,0));
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/2307.cpp

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

 

17182번: 우주 탐사선

우주 탐사선 ana호는 어떤 행성계를 탐사하기 위해 발사된다. 모든 행성을 탐사하는데 걸리는 최소 시간을 계산하려 한다. 입력으로는 ana호가 탐색할 행성의 개수와 ana호가 발사되는 행성의 위

www.acmicpc.net

 

 

[난이도] Gold2
[유형] 플로이드 와샬

[풀이]
플로이드 와샬을 이용해 우주선간 최단 거리를 미리 구해놓은 뒤
방문할 순서를 순열을 이용해 구해준 뒤 각 N!개의 순열에 대해 최단 거리를 계산해주면 됩니다.

 

#include <cstdio>
#include <algorithm>
using namespace std;
int N,K,dist[11][11],seq[11],ans=9e8;
int main(){
    scanf("%d%d",&N,&K);
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++) scanf("%d",&dist[i][j]);

    for(int k=0;k<N;k++)
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
    int j=0;
    for(int i=0;i<N;i++) if(i!=K) seq[j++]=i;
    do{ 
        int t=dist[K][seq[0]];
        for(int i=1;i<N-1;i++) t+=dist[seq[i-1]][seq[i]];
        ans=min(t,ans);
    }while(next_permutation(seq,seq+N-1));
    printf("%d",ans); 
}


https://github.com/has2/Problem-Solving/blob/master/boj-solved.ac/Gold2/17182.cpp

+ Recent posts