- 1940번  주몽 

 

1940번: 주몽

첫째 줄에는 재료의 개수 N(1 ≤ N ≤ 15,000)이 주어진다. 그리고 두 번째 줄에는 갑옷을 만드는데 필요한 수 M(1 ≤ M ≤ 10,000,000) 주어진다. 그리고 마지막으로 셋째 줄에는 N개의 재료들이 가진 고

www.acmicpc.net

<풀이>

어제 푼 문제 복습 겸 투포인터 문제를 풀어보았다.. 어제 문제랑 접근 법이 아주 동일하다

필요한 수 값의 범위 때문에 for문을 돌릴경우 당연히 시간초과가 발생한다. 고로 투포인터로 접근하면 된다.

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int n,m;
vector<int> vec;

int main(void){
   cin>>n;
   cin>>m;
   for(int i=0; i<n; i++){
       int num;
       cin>>num;
       vec.push_back(num);
   }

   sort(vec.begin(),vec.end());
   int left = 0 , right = n-1, cnt =0;
   while(left<right){
       int sum = vec[left]+vec[right];
       if(sum == m) {
           cnt++;
           right--;
       }
       else if(sum>m){
           right--;
       }
       else left++;
   }
    
    cout<<cnt<<"\n";
}

 

 

- 1806번 부분합

 

1806번: 부분합

첫째 줄에 N (10 ≤ N < 100,000)과 S (0 < S ≤ 100,000,000)가 주어진다. 둘째 줄에는 수열이 주어진다. 수열의 각 원소는 공백으로 구분되어져 있으며, 10,000이하의 자연수이다.

www.acmicpc.net

<풀이>

투포인터 재밌네,, 이 문제 또한 투포인터 !!!! 

1. 시작 점 부터 더해주면서 해당 값에 도달or 넘었는지 확인

2. 넘었다면 도달한 거리를 갱신해주고 ->최단거리를 구하기 위해 시작점을 이동시켜주며 더해준 값을 빼줌

3. 합이 아직 부족하다면 배열의 길이를 늘려간다  / 이 때 배열에 끝에 도달했는데도 합을 충족시키지 못한다면 반복문을 나온다

4. 초기값에 따라 부분합을 구할 수 있는지 or 최단거리가 있는지 출력해준다.

 

문제 난이도는 골드인데 위에 푼 실버랑 크게 큰 차이는 없는 느낌..? 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int n,m;
vector<int> vec;

int main(void){
   cin>>n>>m;
  
   for(int i=0; i<n; i++){
       int num;
       cin>>num;
       vec.push_back(num);
   }

   int st =0,end =0, sum=vec[0], ans = 214700000;
   while(st<=end){
       if(sum>=m){
           ans = min(ans, (end-st)+1);
           sum -= vec[st++];
       }
       else if(sum<m){
           if(end == n) break;
           sum +=vec[++end];
       }
   }

   if(ans ==214700000 ) cout<<0<<"\n";
   else cout<<ans<<"\n";
}

 

- 3273번 두 수의 합

 

3273번: 두 수의 합

n개의 서로 다른 양의 정수 a1, a2, ..., an으로 이루어진 수열이 있다. ai의 값은 1보다 크거나 같고, 1000000보다 작거나 같은 자연수이다. 자연수 x가 주어졌을 때, ai + aj = x (1 ≤ i < j ≤ n)을 만족하는

www.acmicpc.net

<풀이>

처음엔 혹시나 하는 마음에 2중 for문을 썼지만, 당연히 시간초과가 떴다. 결국 투포인터로 접근 !

이중 탐색처럼 left , right를 나눠서 vector 에 저장된 값들을 두개씩 더해주면서 합을 비교해줬다. 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

int n,k;
vector<int> vec;
int main(void){
    cin>>n;
    for(int i=0; i<n; i++){
        int num;
        cin>>num;
        vec.push_back(num);
    }
    sort(vec.begin(),vec.end());
    cin>>k;
    
    int left= 0, right =n-1 ,cnt =0;
    while(left<right){
        int sum = vec[left]+vec[right];
        if(sum==k){
            cnt++;
            right--;
        }
        else if(sum>k) right--;
        else left++;
    }
    cout<<cnt<<"\n";
}

 

- 16431번 베시와 데이지

 

16431번: 베시와 데이지

베시는 (3, 5) > (2, 4) > (2, 3) 경로로 이동하여 존에게 오는데 2초가 걸립니다. 반면 데이지는 (1, 1) > (1, 2) > (1, 3) > (2, 3) 경로로 이동하여 존에게 오는데 3초가 걸리므로 베시가 더 빨리 도착합니다.

www.acmicpc.net

<풀이>

간단한 BFS문제였다. 베시 / 데이지 각각 함수를 두 개 구현하려다가.. 그냥 하나에 몰아서 매개변수로 베시/데이지 구별하여 탐색할 수 있도록 구현했다.. 쫌더 짧게 코딩하고 싶어서 그랬는데 오히려 더 지저분해진 기분..

문제 접근은 다음과 같다.

1. 주어진 베시의 시작점에서 존 까지의 이동 시간 기록 ( =  BFS)

2. 주어진 데이지의 시작점에서 존 까지의 이동시간 기록

3. 1,2에서 구한 시간을 비교해서 더 빠르게 도착한 사람의 이름을 출력해주면 된다. 

 

예전에 주구장창 풀었던 최단거리나,, 등등 문제 구현 코드가 다 가물가물해져서 큰일이다 ~ 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <cstring>


using namespace std;

int dx[4] ={-1,0,1,0};
int dy[4] ={0,1,0,-1};
int ddx[8]={-1,-1,-1,0,1,1,1,0};
int ddy[8]={-1,0,1,1,1,0,-1,-1};

int ch[2001][2001];
int px,py;
int BFS(int x, int y, int num){
    queue<pair<int,int> > que;
    memset(ch,0,sizeof(ch));
    que.push(make_pair(x,y));
    ch[x][y] = 1;

    while(!que.empty()){
        int xx= que.front().first;
        int yy =que.front().second;
        que.pop();

        if(xx == px  && yy == py) return ch[xx][yy]-1;
        
        //Bessie
        if(num == 1){
            for(int i=0; i<8; i++){
                int nx = xx + ddx[i];
                int ny = yy + ddy[i];

                if(nx<1 || nx>1001 || ny<1 || ny>1001) continue;
                if(ch[nx][ny]) continue;
                que.push(make_pair(nx,ny));
                ch[nx][ny] = ch[xx][yy] + 1;
            }
        }
        //Daisy
        else if(num == 2){
            for(int i=0; i<4; i++){
                int nx = xx + dx[i];
                int ny = yy + dy[i];

                if(nx<1 || nx>1001 || ny<1 || ny>1001) continue;
                if(ch[nx][ny]) continue;
                que.push(make_pair(nx,ny));
                ch[nx][ny] = ch[xx][yy] + 1;
            }
        }

    }

    return 0;
}

int main(void){
    int ax,ay,bx,by;
    cin>>ax>>ay;
    cin>>bx>>by;
    cin>>px>>py;

    int bessie = BFS(ax,ay,1);
    int daisy = BFS(bx,by,2);
    if(bessie>daisy) cout<<"daisy"<<"\n";
    else if(bessie<daisy) cout<<"bessie"<<"\n";
    else cout<<"tie"<<"\n";

}

 

<양심없는 브론즈 문제 풀이>

- 10988번 팰린드롬인지 확인하기 

 

10988번: 팰린드롬인지 확인하기

첫째 줄에 단어가 주어진다. 단어의 길이는 1보다 크거나 같고, 100보다 작거나 같으며, 알파벳 소문자로만 이루어져 있다.

www.acmicpc.net

<풀이> 

팰린드롬 = 뒤집었을 때도 동일한 경우

1. 문자열 입력받음

2. 입력받은 문자열  reverse함수로 뒤집음

3. 1==2 이면 1출력 아니면 0 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>



using namespace std;

int main(void){
    string st;
    cin>>st;
    string tmp = st;
    reverse(tmp.begin(),tmp.end());

    if(st == tmp) cout<<1<<"\n";
    else cout<<0<<"\n";
}

-2744번 대소문자 바꾸기

 

2744번: 대소문자 바꾸기

영어 소문자와 대문자로 이루어진 단어를 입력받은 뒤, 대문자는 소문자로, 소문자는 대문자로 바꾸어 출력하는 프로그램을 작성하시오.

www.acmicpc.net

<풀이>

그냥 바꿔주면 됩니다...

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>

using namespace std;

int main(void){
    string st;
    cin>>st;
    string tmp="";
    for(int i=0; i<st.size(); i++){
        if(st[i]>='a' && st[i]<='z'){
            tmp+=st[i]-'a'+'A';
        }
        else tmp+= st[i]-'A'+'a';
    }
    cout<<tmp<<"\n";
}

-9933번 민균이의 비밀번호

 

9933번: 민균이의 비밀번호

첫째 줄에 단어의 수 N (2 ≤ N ≤ 100)이 주어진다. 다음 N개 줄에는 파일에 적혀있는 단어가 한 줄에 하나씩 주어진다. 단어는 알파벳 소문자로만 이루어져 있으며, 길이는 2보다 크고 14보다 작은

www.acmicpc.net

<풀이>

자기자신부터 체크하라는 부분을 빼먹어서 한번 틀렸다 .... 

입력되는 단어 중에 비밀번호가 되려면 뒤집은 단어도 존재해야한다.

이 문제는 다음과 같이 접근했다.

1. 단어의 수 만큼 벡터에 일단 다 저장

2. 단어의 수 만큼 하나씩 뒤집어주고, 자기 자신부터 뒤집었을 때의 값과 동일한 경우 (=비밀번호) 바로 출력해주고 멈춤 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <vector>

using namespace std;

int main(void){
    int n;
    cin>>n;
    vector<string> vec;
    for(int i=0; i<n; i++){
        string st;
        cin>>st;
        vec.push_back(st);
    }
  
    for(int i=0; i<vec.size(); i++){
        string tmp = vec[i];
        reverse(tmp.begin(),tmp.end());
        for(int j=0; j<vec.size(); j++){
            if(tmp == vec[j]) {
                cout<<tmp.size()<<" "<<tmp[tmp.size()/2]<<"\n";
                return 0;
            }
        }
    }
    
}

정말 오랜만에.. 백준을 다시 푼다....ㄱ- 

 

- 1189번 컴백홈

 

1189번: 컴백홈

첫 줄에 정수 R(1 ≤ R ≤ 5), C(1 ≤ C ≤ 5), K(1 ≤ K ≤ R×C)가 공백으로 구분되어 주어진다. 두 번째부터 R+1번째 줄까지는 R×C 맵의 정보를 나타내는 '.'과 'T'로 구성된 길이가 C인 문자열이 주어진다

www.acmicpc.net

<풀이>

기억을 살릴 겸.. 백트래킹 문제를 풀어보았다. 주어진 조건대로 차분이 구현하면 되는 문제였다.

1. 왼쪽 아래에서 시작 

2. 오른쪽 위 목적지 (=집) 에 도달하는데, 길이가 K 이며 지난 곳을 다시 방문하지 않음 (= 체크 배열이 필요함)

3. 집에 갈 수 있는 모든 경우의 수를 찾아야함 = 백트래킹 

 

재귀함수를 호출할 때, 함수 종료 조건은 2번에 명시한 것과 같다. 

즉, (x,y) 상하좌우 이동하며 제일 오른쪽 상단에 도달 & 거기 까지 도달하는 길이가 K 이면 재귀함수를 종료하고 카운트를 해주면 된다.

 

알고리즘 실력 쌓기는 너무나 힘든데,, 쫌 쉬었다고 바로 리셋됐음..하 ^^... 쉽지않네 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

int dx[4] = {-1,0,1,0};
int dy[4] ={0,1,0,-1};
int ch[6][6];
string board[6];
int n,m,k;
int num; 

void DFS(int x, int y, int cnt){
    if(x == 0 && y == m-1 && cnt == k){
        num++;
        return;
    }
    else{
        for(int i=0; i<4; i++){
            int nx = x + dx[i];
            int ny = y + dy[i];
            if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
            if(board[nx][ny] == 'T' || ch[nx][ny]) continue;
            ch[nx][ny] = 1;
            DFS(nx,ny, cnt+1);
            ch[nx][ny] = 0;
            
        }
    }
}

int main(void){
    cin>>n>>m>>k;

    for(int i=0; i<n; i++){
        cin>>board[i];
    }
    
    ch[n-1][0] = 1;
    DFS(n-1,0,1);
    cout<<num<<"\n";
}

 

 

- 1316번 그룹 단어 체커

 

1316번: 그룹 단어 체커

그룹 단어란 단어에 존재하는 모든 문자에 대해서, 각 문자가 연속해서 나타나는 경우만을 말한다. 예를 들면, ccazzzzbb는 c, a, z, b가 모두 연속해서 나타나고, kin도 k, i, n이 연속해서 나타나기 때

www.acmicpc.net

<풀이>

1. 입력된 문자열의 길이만큼 탐색하면서 알파벳 등장 횟수를 세어준다

2. 조건에 따르면 이미 나온 알파벳인데, 연속해서 나오지 않은경우 = 그룹단어 아님 

3. 2번 조건에 따라 그룹 단어 체커만 카운트 해준다. 

 

문제 자체는 어렵지 않고 .. 문자열 마다 초기화만 잘 해주면 된다..

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <string>

using namespace std;

int ap[30];
int n, ans;
bool check;
string str;

int main(void){
    cin>>n;
    
    while(n--){
        cin>>str;
        memset(ap,0,sizeof(ap));
        check = true;

        for(int i=0; i<str.size(); i++){
            int idx = str[i]-'a';
            if(ap[idx]){
                if(str[i-1] != str[i]){
                    check = false;
                }
            }
            ap[idx]++;
        }

        if(check) ans++;
    }

    cout<<ans<<"\n";
}

- 6497번 전력난

 

6497번: 전력난

성진이는 한 도시의 시장인데 거지라서 전력난에 끙끙댄다. 그래서 모든 길마다 원래 켜져 있던 가로등 중 일부를 소등하기로 하였다. 길의 가로등을 켜 두면 하루에 길의 미터 수만큼 돈이 들

www.acmicpc.net

<풀이>

하루 쉬었다고 이렇게 머리가 리셋될 수 있나..  이번주 코테인데....실력이 아찔하다..^^..

최소 스패닝 문제를 풀어봤다 며칠전에 풀었던 문제와 유사한데 차이점은 좀 특이하게 다른 문제들처럼 테스트케이스 개수가 나와있지 않고,  0 0  입력되면 종료 이런식으로 나와있었다. 게다가 테케 1이 테케 한 개만 입력되고 끝이라 아무생각없이 제출했더니 50%에서 오류가 났다. 

0 0 이 나오면 리턴해주고, 0 0 이 나오기 전 까지 여러 번 테케를 받는다는 생각으로 구현해주면 해결 완료..

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;


int unf[200010];
struct State{
    int v1,v2,dis;
    State(int a, int b, int c){
        v1 = a;
        v2 = b;
        dis = c;
    }
    bool operator<(const State &nn) const{
        return dis<nn.dis;
    }
};

int Find(int v){
    if(v==unf[v]) return v;
    else return unf[v] = Find(unf[v]);
}

void Union(int a, int b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}

int n,m,x,y,z,org,sum;

int main(void){
    while(1){
        cin>>n>>m;
        if(n==0 && m==0) return 0;
        org = 0, sum = 0;
        vector<State> vec;
        for(int i=0; i<m; i++){  
            cin>>x>>y>>z;
            vec.push_back(State(x,y,z));
            org+=z;
        }
        for(int i=0; i<n; i++) unf[i] = i;
        sort(vec.begin(),vec.end());
        
        for(int i=0; i<vec.size(); i++){
            int fa = Find(vec[i].v1);
            int fb = Find(vec[i].v2);
            if(fa!=fb){
                Union(fa,fb);
                    sum+=vec[i].dis;
            }
        }
        cout<<org-sum<<"\n";
    }
    return 0;
}

 

- 14912번 숫자 빈도수

 

14912번: 숫자 빈도수

자연수 n (1 ≤ n ≤ 100,000)과 한 자리 숫자 d(0~9)가 첫째 줄에 주어진다.

www.acmicpc.net

<풀이>

오늘은 잘 안풀려서.. 힐링겸.. 귀여운 문제.. 

입력되는 숫자가 2자리이상 인 경우에 계산하기 편하도록 string type으로 변환하여 하나씩 처리해주었다.

각 요소의 개수를 체크하기 위해서 배열 타입을 선언했다. 

의외로 이렇게 숫자-문자 교환해서 처리하는 스타일의 문제가 코테에서 종종 봤던거 같다.. 먼가..그래..

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>

using namespace std;


int n,d;
int arr[10];

int main(void){
    cin>>n>>d;

    for(int i=1; i<=n; i++){
        string s = to_string(i);
        if(s.size()>1){
            for(int j=0; j<s.size(); j++){
                int num = s[j]-'0';
                arr[num]++;
            }
        }
        else{
            arr[i]++;
        }
    }
    cout<<arr[d]<<"\n";
}

 

-9996번 한국이 그리울 땐 서버에 접속하지 

 

9996번: 한국이 그리울 땐 서버에 접속하지

총 N개의 줄에 걸쳐서, 입력으로 주어진 i번째 파일 이름이 패턴과 일치하면 "DA", 일치하지 않으면 "NE"를 출력한다. 참고로, "DA"는 크로아티어어로 "YES"를, "NE"는 "NO"를 의미한다.

www.acmicpc.net

<풀이>

왜요  제가 java에 있는 split 함수 c++에 없어서 코드 길어진 사람처럼 보이시나요? 제대로 보셨습니다..

split이 없어서 find로 * 위치 체크 한 후 앞부분/뒷부분 문자열을 저장해줬다.

체크하는 방식은 앞부분은 차례대로 하면 쉽고.. 뒷부분은 *뒤의 길이 만큼 체크를 해줘야했다.

생각보다 쉽네 하고 제출했더니 63%에서 틀렸습니다가 나왔는데, 반례를 확인하니 중복 되어 체크되는 경우가 있었다...

 

1
abcd*cdef
abcdef 

 

이처럼 나오는 경우에 이미 앞에서 체크 됐으면 중복체크 하면 안된다. 그렇기 때문에 체크 배열을 하나 추가해서

앞에서 체크했으면 표시를 해주고, 뒤에서 체크할때, 이미 중복체크 된 경우도 바로  false을 리턴하게 해주며 해결했다.

이런반례 어떻게 생각하냐... 질문글 없었으면 삽질 오지게했을듯 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;



int n;
int ch[105];
bool check(string f, string b, string target){
    for(int i=0; i<f.size(); i++){
        if(target[i]!=f[i]) return false;
        ch[i] = 1;
    }
    int idx = target.size()-b.size();
    for(int i=0; i<b.size(); i++){
        if(ch[idx] ||target[idx++] != b[i]) return false;
    }
    return true;
}
int main(void){
    string st,ft="",bk="";

    cin>>n;
    cin>>st;
    int idx = st.find('*');
    for(int i=0; i<idx; i++){
        ft+=st[i];
    }
    for(int i=idx+1; i<st.size(); i++){
        bk+=st[i];
    }
    
    for(int i=0; i<n; i++){
        cin>>st;
        if(check(ft,bk,st)){
            cout<<"DA"<<"\n";
        }
        else{
            cout<<"NE"<<"\n";
        }
    }

}

 

 

- 1719번 택배

 

1719번: 택배

명우기업은 2008년부터 택배 사업을 새로이 시작하기로 하였다. 우선 택배 화물을 모아서 처리하는 집하장을 몇 개 마련했지만, 택배 화물이 각 집하장들 사이를 오갈 때 어떤 경로를 거쳐야 하

www.acmicpc.net

<풀이>

예전에 문제 대충읽고 위풍당당 풀다가 틀린 문제 다시 풀어봤다.

출력 모습만 봐도 플로이드-와샬이구나 하고 신나서 풀었는데, 다른문제와 달리 출력해야하는 것이 최단 거리가 아니라 최단 거리로 탐색하며 제일 먼저 만난 정점을 기록하는 거다.

 

1. 최단거리를 비교할 dist 벡터 생성

2. 제일 먼저 만난 정점 기록할 배열 생성

 

즉 만약 a-b-d-c 방식으로 최단거리로 도달했다면, arr[a][c] =  b 가 되어야한다. 

고로 입력할 때 1-1 도착이라 바로 만나는 정점을 넣어주고, 플로이드 와샬 알고리즘을 진행하며 최단 거리가 갱신될 때 젤 먼저 만나는 정점을 넣어줬다.

 

문제를 천천히.. 차분하게 읽는 습관을 기르자..벌써 51일째다....ㄱ-...ㅋㅋㅋㅋ

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>


using namespace std;

int n,m,a,b,c;
int arr[205][205];
int main(void){
    cin>>n>>m;
    vector<vector<int> > dist(n+1, vector<int> (n+1, 21470000));
    for(int i=1; i<=n; i++) dist[i][i] = 0;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        dist[a][b] = c;
        dist[b][a] = c;

        arr[a][b] = b;
        arr[b][a] = a;
    }

    for(int k=1; k<=n; k++){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                if(dist[i][j]>dist[i][k]+dist[k][j]){
                    dist[i][j] = dist[i][k]+dist[k][j];
                    arr[i][j] = arr[i][k];
                }
            }
        }
    }

    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            if(!arr[i][j]) cout<<"-"<<" ";
            else cout<<arr[i][j]<<" ";
        }
        cout<<"\n";
    }

}

 

- 9655번 돌 게임

 

9655번: 돌 게임

상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다.

www.acmicpc.net

<풀이>

DP라며..  상근이가 먼저 겜 시작해서 짝수면 창영 홀수면 상근 출력하면 된다... 이런 개꿀 문제가..?

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>


using namespace std;

int n;
int main(void){
    cin>>n;

    if(n%2) cout<<"SK"<<"\n";
    else cout<<"CY"<<"\n";
}

 

 

- 14405번 피카츄

 

14405번: 피카츄

피카츄는 "pi", "ka", "chu"를 발음할 수 있다. 따라서, 피카츄는 이 세 음절을 합친 단어만 발음할 수 있다. 예를 들면, "pikapi"와 "pikachu"가 있다. 문자열 S가 주어졌을 때, 피카츄가 발음할 수 있는 문

www.acmicpc.net

<풀이>

문자열 문제! 너무 간단하게 생각해서 그런지 실수를 했다. 

처음엔 단순히 해당 위치의 문자를 삭제를 하는식으로 구현했더니 50%대에서 틀렸다.

반례를 찾아보던중 원래는 피/카/츄 문자가 아닌데 삭제를 하면서 이 문자가 되는 상황을 고려해야한다는 걸 떠올릴 수 있었다.

고로 피/카/츄  발음할 수 있는 단어를 만나는 경우 단순히 삭제만 하는 것이 아니라 값이 삭제되며 변경되는 상황을 막아줄 삭제 확인용 문자를 추가하며 구현했다.

 

문자들이 모두 *라면 (= 피카츄로 발음할 수 있음) YES를 출력하고 탐색을 멈춰주었고

혹시나 find함수로 못찾는 경우에는 -1을 인덱스가 리턴하기 때문에 이부분을 기준으로 찾았음 /못찾았음을 체크할 불린 타입 변수를 두어 한번이라도 피/카/츄 단어를 못찾는 경우에는 NO를 출력해주고 탐색을 마무리하도록 구현했다.

 

 

find나 insert등 기본 string내장함수가 정확히 기억 안나서.. 레퍼런스를 찾아본건 안비밀.......

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>


using namespace std;

int main(void){
    string plm[3] = {"pi", "ka", "chu"};

    string str;
    cin>>str;
   
    while(1){
        bool check = false;
        for(int i=0; i<3; i++){
            int idx = str.find(plm[i]);
            if(idx>=0){
                str.erase(idx,plm[i].length());
                str.insert(idx,"*");
                check = true;
            }
        }
        bool ch = true;
        for(int i=0; i<str.size(); i++){
            if(str[i]!= '*'){
                ch = false;
            }
        }
        if(ch){
            cout<<"YES"<<"\n";
            break;
        }
        if(!check){
            cout<<"NO"<<"\n";
            break;
        }
    }
}

 

-2417번 정수 제곱근

 

2417번: 정수 제곱근

정수가 주어지면, 그 수의 정수 제곱근을 구하는 프로그램을 작성하시오.

www.acmicpc.net

<풀이>

다양한.. 알고리즘의 경험을 쌓기 위해.. 오늘은 이분탐색 문제를 풀어보았다.

이분탐색으로 진행하고 찾은 값의 제곱근이 주어진 값과 같으면 출력 아니면 +1 해서 출력해주면 된다.

값 범위가 2^63라서 완탐했으면 무조건 시간초과 -> 이분탐색 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cmath>

using namespace std;



int main(void){
    long long n;
    cin>>n;
    long long left = 0;
    long long right = sqrt(n);
    long long mid;

    while(left<=right){
        mid = (left+right)/2;
        if(mid>=sqrt(n)) right = mid-1;
        else left = mid+1;    
    }

    if(mid*mid == n) cout<<mid<<"\n";
    else cout<<mid+1<<"\n";
   
}

 

- 3079번 입국심사

 

3079번: 입국심사

첫째 줄에 N과 M이 주어진다. (1 ≤ N ≤ 100,000, 1 ≤ M ≤ 1,000,000,000) 다음 N개 줄에는 각 심사대에서 심사를 하는데 걸리는 시간인 Tk가 주어진다. (1 ≤ Tk ≤ 109)

www.acmicpc.net

<풀이>

이번에도 이분탐색 문제 .. 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;



int main(void){
    long long n,m;
    vector<long long> vec;
    cin>>n>>m;
    for(long long i = 0; i<n; i++){
        long long num;
        cin>>num;
        vec.push_back(num);
    }
    sort(vec.begin(),vec.end());
    long long left = 0;
    long long right = m * vec.back();
    long long mid;
    long long ans = right;
    while(left<=right){
        mid = (left+right)/2;
        long long sum = 0;
        for(int i=0; i<vec.size(); i++){
            sum += (mid/vec[i]);
        }
        if(sum>=m){
            ans = min(ans,mid);
            right = mid-1;
        }
        else{
            left = mid+1;
        }
    }
    cout<<ans<<"\n";

}

 

- 4386번 별자리 만들기

 

4386번: 별자리 만들기

도현이는 우주의 신이다. 이제 도현이는 아무렇게나 널브러져 있는 n개의 별들을 이어서 별자리를 하나 만들 것이다. 별자리의 조건은 다음과 같다. 별자리를 이루는 선은 서로 다른 두 별을 일

www.acmicpc.net

<풀이>

마지막은 최소 스패닝 트리-크루스칼 알고리즘 사용 문제를 풀어보았다..

주어진 별자리 조건을 보면 최소 스패닝임을 알 수 있다. (일직선으로 이은 형태 = 즉, 사이클이 없삼)

 

이 문제는 다른 문제와 달리 가중치가 주어져있지 않고, 두 별 사이의 거리만큼의 비용이 든다고 명시되어있다.

고로 직접 입력받은 별자리들 사이의 거리를 구해주어야 했다. 나는 cmath내에  pow, sqrt 함수를 사용했다. 

입력된 거리 비용을 기준으로 오름차순 정렬한 뒤, 별자리를 이어주면 된다. 

이때 혹시나 모든 별자리들 사이의 거리가 입력되어  벡터내에 여러 점이 중복으로 저장되어 있어서 문제가 생기지 않나? 라고 생각을 할 수도 있지만, 최소 스패닝 트리 알고리즘 특징은 이미 연결되어 있는지 체크를 해주기 때문에, 여러 점이 들어가도 문제가 없다..는...점..

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

int unf[100],n;
struct State{
    int v1,v2;
    double dis;
    State(int a, int b, double d){
        v1 = a;
        v2 = b;
        dis = d;
    }
    bool operator<(const State &nn) const{
        return dis<nn.dis;
    }
};

int Find(int v){
    if(v==unf[v]) return v;
    else return unf[v] = Find(unf[v]);
}

void Union(int a, int b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}

double a,b;

int main(void){
    cin>>n;
    for(int i=1; i<=n; i++) unf[i] = i;
    vector<pair<double, double> > vec;
    vector<State> v;
    for(int i=0; i<n; i++){ 
        cin>>a>>b;
        vec.push_back(make_pair(a,b));
    }

    for(int i=0; i<n; i++){
        for(int j=i+1; j<n; j++){
            double x = pow((vec[j].first-vec[i].first),2);
            double y =  pow((vec[j].second-vec[i].second),2);
            double dis = sqrt(x+y);
            v.push_back(State(i,j,dis));
        }
    }

    sort(v.begin(),v.end());
    double ans = 0;
    for(int i=0; i<v.size(); i++){
        int fa = Find(v[i].v1);
        int fb = Find(v[i].v2);
        if(fa!=fb){
            ans+=v[i].dis;
            Union(fa,fb);
        }
    }
    cout<<ans<<"\b";

}

 

 

이젠 걍 습관이 된 거같은 백준 풀기.. 왜 실력은 그대로냐..? 코테 풀때마다 긴장해서 그런거냐,,?

 

 

-14248번 점프 점프 

 

14248번: 점프 점프

첫 번째 줄에는 돌다리의 돌 개수 n이 주어진다.(1≤n≤100,000) 돌의 번호는 왼쪽부터 1번에서 n번이다. 다음 줄에는 그 위치에서 점프할 수 있는 거리 Ai가 주어진다.(1≤Ai≤100,000) 다음 줄에는 출

www.acmicpc.net

<풀이>

예~~~ 전에 풀었던 숨바꼭질 시리즈랑 같다. 일차원 배열을 두고 BFS 탐색 ..  해당 지점의 크기만큼 왼쪽 / 오른쪽 이동이 가능하다고 써있기 때문에 두 가지로 나눠서 탐색을 진행하고, 거쳤으면 체크해주면 된다.

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>


using namespace std;

int n,map[100005],ch[100005];
int st;
int main(void){
    cin>>n;
    for(int i=1; i<=n; i++){
        cin>>map[i];
    }
    cin>>st;
    queue<int > que;
    que.push(st);
    ch[st] = 1;
    int ans = 0;
    while(!que.empty()){
        int x = que.front();
        que.pop();

        int num = map[x];

        if(num+x<100001 && !ch[num+x]){
            que.push(num+x);
            ch[num+x] = 1;
        }

        if(x-num>0 && !ch[x-num]){
            que.push(x-num);
            ch[x-num] = 1;
        }

    }
    for(int i=1; i<=n; i++){
        if(ch[i]) ans++;
    }
    cout<<ans<<"\n";
}

 

 

-1058번 친구 

 

1058번: 친구

지민이는 세계에서 가장 유명한 사람이 누구인지 궁금해졌다. 가장 유명한 사람을 구하는 방법은 각 사람의 2-친구를 구하면 된다. 어떤 사람 A가 또다른 사람 B의 2-친구가 되기 위해선, 두 사람

www.acmicpc.net

<풀이>

플로이드 -와샬로 풀어보았다.. 친구의 수를 세기 위해 친구일때만 거리 배열에 1을 넣어주었다

친구의 수를 세어줄 때 

1. 서로 친구거나

2. 한 다리 건너서 아는 친구 

-> 배열상의 거리가 2이하일 때의 수를 세어주고 이 때의 최댓값을 출력해줬다.

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>


using namespace std;

int n;
int dist[55][55];

int main(void){
    cin>>n;
    char ch;
    for(int i=1; i<=n; i++){
        for(int j=1; j<=n; j++){
            cin>>ch;
            if(i==j) dist[i][j] = 0;
            else if (ch=='Y') dist[i][j] = 1;
            else dist[i][j] = 50000;
        }
    }

    for(int k=1; k<=n; k++){
        for(int i=1; i<=n; i++){
            for(int j=1; j<=n; j++){
                dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
            }
        }
    }

   int ans = 0;

   for(int i=1; i<=n; i++){
       int cnt = 0;
       for(int j=1; j<=n; j++){
           if(i==j) continue;
           else if(dist[i][j]<=2) cnt++;
       }
       ans = max(ans,cnt);
   }
   cout<<ans<<"\n";
}

 

- 10282번 해킹 

 

10282번: 해킹

최흉최악의 해커 yum3이 네트워크 시설의 한 컴퓨터를 해킹했다! 이제 서로에 의존하는 컴퓨터들은 점차 하나둘 전염되기 시작한다. 어떤 컴퓨터 a가 다른 컴퓨터 b에 의존한다면, b가 감염되면

www.acmicpc.net

<풀이>

기본 다익스트라 문제  

조금 다른 점은 a가 b에 의존한다면 b감염시 a가 감염되는 것이라 입력할 때

b->a 방향으로 넣어줘야한다. b가 감염되고 s초 후에 a 가 감염 되는 것이기 때문에..

이 부분과 한 번에 케이스가 여러 개 들어가기 때문에 의존성을 담을 벡터를 잘 초기화 해주는 부분만 체크해주면 된다.

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>


using namespace std;

struct State{
    int pos, dis;
    State(int a, int b){
        pos = a;
        dis = b;
    }
    bool operator<(const State &nn) const{
        return dis>nn.dis;
    }
};
int t,n,d,c,a,b,s;
vector<pair<int,int> > vec[10005];

vector<int> Dijkstra (int st){
    vector<int> dist(n+1, 214700000);
    priority_queue<State> que;
    que.push(State(st,0));
    dist[st] = 0;

    while(!que.empty()){
        int pos = que.top().pos;
        int dis = que.top().dis;
        que.pop();

        if(dis>dist[pos]) continue;

        for(int i=0; i<vec[pos].size(); i++){
            int nxpos = vec[pos][i].first;
            int nxdis = dis + vec[pos][i].second;
            if(nxdis<dist[nxpos]){
                dist[nxpos] = nxdis;
                que.push(State(nxpos,nxdis));
            }
        }
    }

    return dist;
}

int main(void){
    cin>>t;

    while(t--){
        cin>>n>>d>>c;
        
        for(int i=0; i<10005; i++){
            vec[i].clear();
        }

        for(int i=0; i<d; i++){
            cin>>a>>b>>s;
            vec[b].push_back(make_pair(a,s));
        }

        vector<int> v = Dijkstra(c);
        int cnt=0,ans = 0;
        for(int i=1; i<=n; i++){
            if(v[i]!= 214700000){
                cnt++;
                ans = max(ans, v[i]);
            }
        }
        cout<<cnt<<" "<<ans<<"\n";
      


    }
}

 

-13424번 비밀 모임 

 

13424번: 비밀 모임

입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에 테스트 케이스의 개수를 나타내는 자연수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 방

www.acmicpc.net

<풀이>

플로이드 와샬로 풀어보았다.

1. 양방향 통행 가능

2. k명의 친구들이 특정 모임장소 까지 모두 도달가능하며 (초기값이 아니어야한다) 합이 최소일 때

 

처음엔 다익스트라로 하다가 후반에 너무 복잡해질거 같아서 플로이드 와샬로 구현했다.

양방향 통행 가능하기 때문에 거리 벡터에 입력받고, 알고리즘을 실행했다.

플로이드와샬 경우에 dist[a][b] = c 는 a에서  b로 갈때의 거리가 c 라는 의미이기 때문에 이걸 잘 생각해주면서 이용했다.

그 다음 k명만큼 입력받고, 벡터에 일단 저장을 해주었다.

다음에 입력된 k명 만큼 1부터 n까지의 모든 모임 장소가 될 수 있는 경우의 수를 모두 살펴보았다.

해당 모임장소에서 벡터에 저장해둔 k명의 위치를 지나며 그 거리의 합이 최소라면 갱신해주고, 모임장소의 위치를 기억해주었다. 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>


using namespace std;

int t,n,m,a,b,c,k;

int main(void){
    cin>>t;
    while(t--){
        cin>>n>>m;
        vector<vector<int> > dist(n+1, vector<int> (n+1, 21470000));

        for(int i=1; i<=n; i++) dist[i][i] = 0;

        for(int i=0; i<m; i++){
            cin>>a>>b>>c;
            dist[a][b] = c;
            dist[b][a] = c;
        }
        
        for(int k=1; k<=n; k++){
            for(int i=1; i<=n; i++){
                for(int j=1; j<=n; j++){
                    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
                }
            }
        }


        cin>>k;
        vector<int> vec;
        for(int i=0; i<k; i++){
            int num;
            cin>>num;
            vec.push_back(num);
        }

        int ans = 21470000,idx = 0;
        for(int i=1; i<=n; i++){
            int tmp = 0;
            for(int j=0; j<k; j++){
                tmp += dist[i][vec[j]];
            }
            if(ans>tmp){
                ans = tmp;
                idx = i;
            }
        }

        cout<<idx<<"\n";

        

    }
}

 

-21924번 도시 건설

 

21924번: 도시 건설

첫 번째 줄에 건물의 개수 $N$ $(3 \le N \le 10^5 )$와 도로의 개수 $M$ $(2 \le M \le min( {N(N-1) \over 2}, 5×10^5)) $가 주어진다. 두 번째 줄 부터 $M + 1$줄까지 건물의 번호 $a$, $b$ $(1 \le a, b \le N, a ≠ b)$와 두

www.acmicpc.net

<풀이>

이건 최소 스패닝 트리 - 크루스칼 알고리즘을 사용했다. 어쩌다 보니 오늘은 다 최단거리.. 문제네..

이 문제는 범위때문에 변수 선언에 고민을 좀 했는데.. 아슬아슬하거나 적은 것 보단 큰게 낫다 싶어서 long long 으로 선언했다.

 

일단 양방향이며/ 모든 건물이 연결되도록 최소한의 도로  = 최소 스패닝 트리 임을 확인할 수 있었다.

원하는 결과는 초기 비용 - 최소한의 도로  = 절약한 비용을 구해야 한다.

예외로 모든 건물을 연결하지 못할 때의 -1 출력도 고려해 주어야했다. 

-> 이건 최소 스패닝 트리의 특징을 이용하면 쉽다. n개의 정점을 가진 최소 스패닝 트리는 간선의 연결 개수가 n-1개여야 모든 정점을 연결한 것이기 때문에,  연결 횟수가 n-1개가 아니라면 -1을 출력하도록 구현했다. 

 

 평소 스패닝 트리 구현 방법처럼  union- find 함수를 구현하고, 비용을 오름 차순으로 정렬해 최소의 비용으로 연결해주도록 구현했다.

그리고 초기에 구했던 초기 연결 비용에서 간선 연결 횟수가 n-1 인경우에 구한 합을 빼주며 결과를 도출했다.

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>


using namespace std;

long long unf[100001];
int n,m,a,b;
long long c,org;

struct State{
    int v1,v2;
    long long dis;
    State(int a, int b, long long c){
        v1 = a;
        v2 = b;
        dis = c;
    }
    bool operator<(const State &nn) const{
        return dis<nn.dis;
    }
};

long long Find(int v){
    if(unf[v] == v) return v;
    else return unf[v] = Find(unf[v]);
}

void Union(long long a, long long b){
    a = Find(a);
    b = Find(b);
    if(a!=b) unf[a] = b;
}

int main(void){
    ios_base :: sync_with_stdio(false); 
    cin.tie(NULL); 
    cout.tie(NULL);
    cin>>n>>m;
    for(int i=1; i<=n; i++){
        unf[i] = i;
    }
    vector<State> vec;
    for(int i=0; i<m; i++){
        cin>>a>>b>>c;
        vec.push_back(State(a,b,c));
        org+=c;
    }
    sort(vec.begin(),vec.end());
    int cnt = 0;
    long long sum = 0;

    for(int i=0; i<m; i++){
        long long fa = Find(vec[i].v1);
        long long fb = Find(vec[i].v2);
        if(fa!=fb){
            sum += vec[i].dis;
            cnt++;
            Union(fa,fb);
        }
    }

    if(cnt == n-1){
        cout<<org-sum<<"\n";
    }
    else cout<<-1<<"\n";
}

 

 

- 16449번 동일한 단어 그룹화 하기 

 

16499번: 동일한 단어 그룹화하기

첫째 줄에 단어의 개수 N이 주어진다. (2 ≤ N ≤ 100) 둘째 줄부터 N개의 줄에 단어가 한 줄에 하나씩 주어진다. 단어는 알파벳 소문자로만 이루어져 있고, 길이는 10을 넘지 않는다.

www.acmicpc.net

<풀이>

1. string 으로 입력받고, 정렬을 위해 char type벡터에 넣음

2. 벡터를 알파벳 순으로 정렬

3. 정렬된 값을 string으로 중복 체크를 위해 set 에 넣음

 

즉, 중복 체크를 위해 set을 사용하였고, 같은 문자인지 비교하려면 알파벳 순으로 문자들이 정렬되어야 판별가능하기 때문에 벡터에 넣어서 정렬해주었다... 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <set>

using namespace std;
int n;

int main(void){
    cin>>n;
    set<string> st;
    while(n--){
        string str; 
        cin>>str;
        vector<char> vec;
        for(int i=0; i<str.size(); i++){
            vec.push_back(str[i]);
        }
        sort(vec.begin(),vec.end());
        string tmp="";
        for(int i=0; i<vec.size(); i++){
            tmp+=vec[i];
        }
        st.insert(tmp);
    }

    cout<<st.size()<<"\n";
}

 

- 2002번 추월

 

2002번: 추월

입력은 총 2N+1개의 줄로 이루어져 있다. 첫 줄에는 차의 대수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 대근이가 적은 차량 번호 목록이 주어지고, N+2째 줄부터 N개의 줄에는 영식이

www.acmicpc.net

<풀이>

1. map을 사용하여 차량과 터널로 들어온 순서를 기록

2. vector<string>으로 나간 순서를 기록

3. for문을 돌면서 나올 때 순서가 빠른 차부터 더 늦은 차량을 확인하며 추월했는지 판단 ... 개 하기싫군요

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>
#include <map>

using namespace std;
int n,ans;
int main(void){
    cin>>n;
    map<string,int> mp;
    for(int i=0; i<n; i++){
        string str;
        cin>>str;
        mp.insert(make_pair(str,i));
    }

    vector<string> vec;
   for(int i=0; i<n; i++){
       string str;
       cin>>str;
       vec.push_back(str);
   } 
   for(int i=0; i<n; i++){
       for(int j=i+1; j<n; j++){
           if(mp[vec[i]]>mp[vec[j]]){
               ans++;
               break;
           }
       }
   }
   cout<<ans<<"\n";
   
}

 

- 18429번 근손실

 

18429번: 근손실

웨이트 트레이닝을 좋아하는 어떤 대학원생은, 현재 3대 운동 중량 500의 괴력을 소유하고 있다. 다만, 하루가 지날 때마다 중량이 K만큼 감소한다. 예를 들어 K=4일 때, 3일이 지나면 중량이 488로

www.acmicpc.net

<풀이>

순열 + 백트래킹

 

1. 순서가 상관있는 순열을 사용해 n 개를 뽑아준다. ( n개의 서로 다른 키트를 n 일 동안 한 번씩만 사용할 수 있기때문) 

2. 순열로 뽑은 경우 초기 중량은 500이며/ 각 키트를 사용하면 중량이 해당 키트의 값 만큼 늘고, 하루가 지나면 k 만큼 중량이 줄게 된다.

이때 준 중량이 500미만이라면 해당 안되는 운동 프로그램이다.

3. n 개의 순서로 뽑은 운동 프로그램을 진행한 경우 중량이 500미만이 아니라면 그 때 개수를 세어준다.

 

프로그램 순서에 따라 값이 달라질 수 있다 - 순열 ( 순서를 고려해주고 선택)

모든 경우의 수를 체크하기 위해 + 가지치기 - 백트래킹

 

한 번에 통과해서 기분은 조쿤요..

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>


using namespace std;

int n,k,cnt;
int arr[10], ch[10];
vector<int> vec; 
void DFS(int L){
    if(L==n){
        int sum = 500;
        bool check = true;
        for(int i=0; i<vec.size(); i++){
            sum += vec[i]-k;
            if(sum<500){
                check = false;
                break;
            }
        }
        if(check) cnt++;
        return; 
    }
    else{
        for(int i=0; i<n; i++){
            if(!ch[i]){
                ch[i] = 1;
                vec.push_back(arr[i]);
                DFS(L+1);
                vec.pop_back();
                ch[i] = 0;
            }
        }
    }
}

int main(void){
    cin>>n>>k;
    for(int i=0; i<n; i++){
        cin>>arr[i];
    }
    DFS(0);
    cout<<cnt<<"\n";
}

   

- 1245번 농장 관리 

 

1245번: 농장 관리

첫째 줄에 정수 N(1<n≤100), m(1<m≤70)이="" 주어진다.="" 둘째="" 줄부터="" n+1번째="" 줄까지="" 각="" 줄마다="" 격자들의="" 높이를="" 의미하는="" m개의="" 정수가="" 입력된다.<="" p=""> </n≤100),>

www.acmicpc.net

<풀이>

며칠 쉬었더니 벌써 머리 리셋된 기분 .. 내 머리는 휘발성 ^^... 

DFS를 사용한 그래프 문제를 풀어보았다.  뭘 풀까 하다가 정말 끌리는 이름의 문제집을 발견해서 ^^..

압도적 공감하고.. 풀었다.

산봉우리는 주변 인접한 (x,y각 좌표의 차이 모두 1이하 = 대각선까지 체크해야함) 격자들 보다 높아야하기 때문에 .. 여기서 놓친 부분은 높이가 하나인줄 알았는데, 같은 높이를 가지는 하나의 격자 혹은 인접한 격자들의 집합 까지 될 수 있었다.... 그렇다.. 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

int n,m,ans;
int map[105][105],ch[105][105];
int dx[8] ={-1,-1,-1,0,1,1,1,0};
int dy[8] ={-1,0,1,1,1,0,-1,-1};
bool check =true;
void DFS(int x, int y){
    for(int i=0; i<8; i++){
        int nx = x+ dx[i];
        int ny = y + dy[i];
        if(nx<0 || nx>=n || ny<0 || ny>=m) continue;
        if(map[x][y]<map[nx][ny]) check = false;
        if(ch[nx][ny] || map[x][y]!=map[nx][ny]) continue;
    
        ch[nx][ny] = 1;
        DFS(nx,ny);
    }
}

int main(void){
    cin>>n>>m;
    
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin>>map[i][j];    
        }
    }

    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            if(!ch[i][j]){
                check = true;
                DFS(i,j);
                if(check) ans++;
            }
        }
    }
    cout<<ans<<"\n";
   
}

 

- 2204번 도비의 난독증 테스트

 

2204번: 도비의 난독증 테스트

꿍은 도비에게 영어단어들을 제시한 후 어떤 단어가 대소문자를 구분하지 않고 사전순으로 가장 앞서는지 맞추면 양말을 주어 자유를 얻게해준다고 하였다. 하지만 인성이 좋지 않은 꿍은 사실

www.acmicpc.net

<풀이>

혹시나 하는 소망에 정렬이 대소문자 구분을 안해줬으면 하는 마음으로 그냥 정렬했지만, 역시나 똑똑하게 구분해준다.

다음 생각한건 pair의 특성을 이용한 것이다. pair 의 경우 첫번째 요소를 기준으로 우선 정렬하고, 첫 번째가 같으면 두 번째 요소를 기준으로 정렬한다. 하지만 중복된 단어가 안나온다 했으니, 그냥 단순히 원본 저장용으로 사용했다.

 

1. 정렬을 위해 <모두 소문자로 변경된 문자 , 원본문자>  방법으로 넣어준다.

2. 정렬을하면 첫번째 기준으로 모두 정렬되기 때문에, 맨 앞부분의 원본을 뽑아주면 된다. 

 

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

int main(void){
    while(1){
        int n;
        cin>>n;
        if(n==0) return 0; 
        vector<pair<string, string> > vec;
        string str;
        for(int i=0; i<n; i++){
            cin>>str;
            string tmp = str;
            for(int i=0; i<str.size(); i++){
                if(str[i]>='A' && str[i]<='Z'){
                    str[i] = str[i]-'A'+'a';
                }
            }
            vec.push_back(make_pair(str,tmp));
        }

        sort(vec.begin(),vec.end());
        cout<<vec.front().second<<"\n";
    }
}

 

- 2941번 크로아티아 알파벳

 

2941번: 크로아티아 알파벳

예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다. 크로아티아 알파벳 변경 č c= ć c- dž dz= đ d- lj lj nj nj š s= ž z=

www.acmicpc.net

<풀이>

string find,  replace함수 사용

크로아티아 알파벳을 벡터에 미리 다 저장을 하고, 탐색을 진행했다.

앞 뒤 문자가 합쳐지면서 알파벳이 완성되면 안되기때문에 크로아티아 알파벳을 찾으면 치환해줬다.

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <string>

using namespace std;

int main(void){
   vector<string>  vec = {"c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z="};
   string str;
   cin>>str;
  
   for(int i=0; i<vec.size(); i++){
       while(1){
           int idx = str.find(vec[i]);
           if(idx == string::npos) break;
           str.replace (idx , vec[i].length(), "#");
       }
   }

   cout<<str.size()<<"\n";
}

+ Recent posts