반응형

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

 

4256번: 트리

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 노드의 개수 n이 주어진다. (1 ≤ n ≤ 1,000) BT의 모든 노드에는 1부터 n까지 서로 다른 번호가 매겨져 있다. 다음

www.acmicpc.net

1. 문제설명

트리의 전위순회 결과와 중위순회 결과를 바탕으로 트리의 구조를 구해낼 수 있고,

이를 후위순회한 결과를 출력하는 문제이다.

 

전위 순회한 결과 먼저오는 노드가 루트노드임을 알 수 있고,

그 루트노드를 바탕으로 중위순회 결과를 보면

해당 루트노드의 왼쪽 서브트리와 오른쪽 서브트리를 알 수 있다.

 

이를 재귀적으로 구현하면 트리 구조를 구현할 수 있고,

이를 후위순회하면  정답이 된다.

 

 

 

 

 

2. 문제풀이코드

#include <bits/stdc++.h>
using namespace std;

int n,pidx, preOrderRes[1001], inOrderRes[1001], order[1001];

struct Node{
    int data;
    Node* left = nullptr;
    Node* right = nullptr;
    Node(int _data, Node* _left, Node* _right): data(_data), left(_left), right(_right){}
};


void postOrder(Node* root){
    if(root== nullptr) return;
    postOrder(root->left);
    postOrder(root->right);
    cout << root->data << ' ';
}

void deconstruct(Node* root){
    if(root == nullptr) return;
    deconstruct(root->left);
    deconstruct(root->right);
    root = nullptr;
    delete root;
}


Node* makeTree(int start, int end){
    if(start > end) return nullptr;
    
    Node* newNode = new Node(preOrderRes[pidx++], nullptr, nullptr);
    if(start==end) return newNode;
    int mid = order[newNode->data];
    newNode->left = makeTree(start, mid-1);
    newNode->right = makeTree(mid+1, end);
    return newNode;
}

void makeTree(Node** root){
    pidx = 1;
    *root = makeTree(1, n);
}



int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int t;
    cin >> t;
    for(int T=0; T<t; T++){
        cin >> n;
        for(int i=1; i<=n; i++){
            cin >> preOrderRes[i];
        }
        for(int i=1; i<=n; i++){
            cin >> inOrderRes[i];
            order[inOrderRes[i]] = i;
        }
        Node *root = nullptr;

        makeTree(&root);
        postOrder(root);
        cout << '\n';
        deconstruct(root);
    }

    return 0;
}
반응형
반응형

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

 

5639번: 이진 검색 트리

트리를 전위 순회한 결과가 주어진다. 노드에 들어있는 키의 값은 106보다 작은 양의 정수이다. 모든 값은 한 줄에 하나씩 주어지며, 노드의 수는 10,000개 이하이다. 같은 키를 가지는 노드는 없다

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;

struct Node{
    int data;
    Node* left;
    Node* right;

    Node(int _data, Node* _left, Node* _right): data(_data), left(_left), right(_right){};
};


void insert(Node** root,int value){
    Node* p = *root, *q = nullptr;

    while(p != nullptr){
        q = p;
        if(value < p->data){
            p = p->left;
        }
        else p = p->right;
    }

    Node* newNode = new Node(value, nullptr, nullptr);
    if(q == nullptr){
        *root = newNode;
    }
    else if(value < q->data){
        q->left = newNode;
    }
    else{
        q->right = newNode;
    }
}


void postOrder(Node* root){
    if(root== nullptr) return;
    postOrder(root->left);
    postOrder(root->right);
    cout << root->data << '\n';
}


int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int num;
    Node* root = nullptr;
    while(cin >> num){
        insert(&root, num);
    }
    postOrder(root);

    return 0;
}

 

반응형
반응형

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

 

2250번: 트리의 높이와 너비

첫째 줄에 노드의 개수를 나타내는 정수 N(1 ≤ N ≤ 10,000)이 주어진다. 다음 N개의 줄에는 각 줄마다 노드 번호와 해당 노드의 왼쪽 자식 노드와 오른쪽 자식 노드의 번호가 순서대로 주어진다.

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;
const int MX = 10003;

int column[MX] , N, root , order, totalLev;
int adj[MX][2], revAdj[MX][2];
vector<int> level[MX];


//root 노드 찾기
int findRoot(int node){
    bool ch[N+1];
    memset(ch, 0 , sizeof(ch));
    queue<int> Q;

    ch[node] = 1;
    Q.push(node);
    while(!Q.empty()){
        int cur = Q.front(); Q.pop();
        if(revAdj[cur][0] == 0 && revAdj[cur][1] == 0){
            return cur;
        }

        for(int i=0; i<2; i++){
            int nxt = revAdj[cur][i];
            if(nxt == 0 || nxt == -1) continue;

            if(!ch[nxt]){
                ch[nxt] = 1;
                Q.push(nxt);
            }
        }
    }
    return -1;
}

void getLevel(int node){
    bool ch[N+1];
    memset(ch, 0 , sizeof(ch));

    queue<int> Q;

    ch[node] = 1;
    Q.push(node);

    while(!Q.empty()) {
        int curSize = Q.size();
        totalLev++;
        for(int i=0; i<curSize; i++){
            int cur = Q.front(); Q.pop();
            level[totalLev].push_back(cur);

            for(int j=0; j<2; j++){
                int nxt = adj[cur][j];
                if(nxt == 0 || nxt == -1) continue;
                if(!ch[nxt]){
                    ch[nxt] = 1;
                    Q.push(nxt);
                }
            }
        }
    }
}


void inOrder(int node){
    if(node == -1) return;
    inOrder(adj[node][0]);
    column[node] = ++order;
    inOrder(adj[node][1]);
}


int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    cin >> N;

    for(int i=0; i<N; i++){
        int a, b, c;
        cin >> a >> b >> c;
        adj[a][0] = b;
        adj[a][1] = c;

        revAdj[b][0] = a;
        revAdj[c][1] = a;
    }

    root = findRoot(N);

    getLevel(root);
    inOrder(root);

    int ansLev = 0, ansWidth = 0;

    for(int i=1; i<=totalLev; i++){
        int minn = 10003, maxx = -1;

        for(auto num : level[i]){
            minn = min(column[num], minn);
            maxx = max(column[num], maxx);
        }

        int curWidth = maxx - minn + 1;

        if(curWidth > ansWidth){
            ansWidth = curWidth;
            ansLev = i;
        }
    }
    
    cout << ansLev << ' ' << ansWidth <<'\n';




    return 0;
}
반응형
반응형

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

 

5670번: 휴대폰 자판

휴대폰에서 길이가 P인 영단어를 입력하려면 버튼을 P번 눌러야 한다. 그러나 시스템프로그래밍 연구실에 근무하는 승혁연구원은 사전을 사용해 이 입력을 더 빨리 할 수 있는 자판 모듈을 개발

www.acmicpc.net

1. 문제설명

휴대폰 자판을 입력할 때 자동완성기능이 존재하면,

특정 단어를 입력하기 위해서 자판을 몇번 눌러야 하는지 계산하는 문제이다.

 

단어 리스트가 주어지고, 각 단어마다 몇번 눌러야하는지 구하는 과정에서

트라이 알고리즘을 이용해야 문제를 시간내에 해결할 수 있다.

 

 

5670 트라이

주어진 단어로 위와 같이 트리를 미리 구현하고

분기점과 단어가 끝나는 지점마다 카운트해주어야

하나의 단어를 입력하기 위해 자판을 몇번 입력해야하는지 알아낼 수 있다.

 


 

2. 문제풀이코드 C++

#include <bits/stdc++.h>
#define ALPHABETS 26
using namespace std;


const int ROOT = 1;
int unused = 2;
const int MX = 1000'003;
int nxt[MX][26];
bool chk[MX];
int childs[MX];

int ctoi(char c){
    return c-'a';
}

void insert(string &s){
    int cur = ROOT;
    for(auto c : s){
        if(nxt[cur][ctoi(c)] == -1){
            childs[cur]++;
            nxt[cur][ctoi(c)] = unused++;
        }
        cur = nxt[cur][ctoi(c)];
    }
    chk[cur] = true;
}


int count(string &s){
    int res = 1;

    int cur = ROOT;
    for(int i=0; i<s.length();i++){
        cur = nxt[cur][ctoi(s[i])];

        if(i!=s.length()-1 && (childs[cur] > 1||chk[cur])){
            res++;
        }
    }
    return res;
}


vector<string> words;



int n;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    while(cin >> n){
        words.clear();
        unused = 2;

        fill(childs, childs+MX , 0);
        fill(chk, chk+MX, 0);
        for(int i=0; i<MX; i++){
            fill(nxt[i], nxt[i]+26, -1);
        }

        for(int i=0; i<n; i++){
            string s;
            cin >> s;
            insert(s);
            words.push_back(s);
        }


        double sum = 0;
        for(auto s : words){
//            cout << s << '\n';
//            cout << count(s) << '\n';
            sum += count(s);
        }


        cout << fixed;
        cout.precision(2);
        cout << sum / n << '\n';



    }

    return 0;
}
반응형
반응형

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

 

1167번: 트리의 지름

트리가 입력으로 주어진다. 먼저 첫 번째 줄에서는 트리의 정점의 개수 V가 주어지고 (2 ≤ V ≤ 100,000)둘째 줄부터 V개의 줄에 걸쳐 간선의 정보가 다음과 같이 주어진다. 정점 번호는 1부터 V까지

www.acmicpc.net

1.문제설명

트리의 지름을 구하는 방법은 다음과 같다.

 

아무 노드 A를 택하고, A노드와 가장 멀리있는 노드 B를 찾는다.(BFS or DFS 아무거나 사용해도 된다)

 

그리고 노드 B와 가장 멀리 있는 노드 C를 찾아서

노드 B와 노드 C의 거리를 구하면 그게 트리의 지름이 된다.

 

현재 문제에서 노드간의 거리가 다른데

이 문제는 최단경로를 찾는 문제가 아니므로 다익스트라 알고리즘을 사용할 필요는 없고

BFS로 가장 먼 거리에 있는 노드를 찾아주기만 하면된다.

 

 

2.문제풀이코드

import java.io.*;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

class Pair{
    int node , dist;
    Pair(int node, int dist){
        this.node = node;
        this.dist = dist;
    }
}

public class main {
    static ArrayList<Pair>[] adj;
    static int V;
    static Queue<Pair> Q;

    //start node로 부터 가장 멀리 있는 node와 거리를 구하는 함수
    static Pair bfs(int start){
        int end = 0;
        int dist = 0;
        boolean[] visit = new boolean[V+1];
        visit[start] = true;
        Q.add(new Pair(start, 0));

        while(!Q.isEmpty()){
            Pair cur = Q.poll();
            if(cur.dist > dist){
                end = cur.node;
                dist = cur.dist;
            }

            for(int i=0; i<adj[cur.node].size(); i++){
                int nextNode = adj[cur.node].get(i).node;
                int addDist = adj[cur.node].get(i).dist;

                if(!visit[nextNode]){
                    visit[nextNode] = true;
                    Q.add(new Pair(nextNode, cur.dist + addDist));
                }
            }
        }

        return new Pair(end, dist);
    }



    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());

        V = Integer.parseInt(st.nextToken());
        adj = new ArrayList[V+1];
        Q = new LinkedList<>();

        for(int i=1; i<=V; i++){
            adj[i] = new ArrayList<>();
        }

        for(int i=1; i<=V; i++){
            st = new StringTokenizer(br.readLine());
            int curNode = Integer.parseInt(st.nextToken());
            int connectNode = Integer.parseInt(st.nextToken());
            
            while(connectNode!=-1){
                int dist = Integer.parseInt(st.nextToken());
                adj[curNode].add(new Pair(connectNode, dist));
                connectNode = Integer.parseInt(st.nextToken());
            }
        }

        Pair start = bfs(1);
        Pair ans = bfs(start.node);
        bw.write(ans.dist+"");
        bw.flush();
        bw.close();
    }
}

 

반응형
반응형

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

 

1914번: 하노이 탑

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로

www.acmicpc.net

큰 수의 계산을 잘 구현해야 하는 문제이다.

2^100은

10^34 정도 되기 때문에

long long 은 최대 19자리이므로 long long 2개를 붙여쓰면 38자리까지 구현이 가능하다.

 

#include <bits/stdc++.h>
using namespace std;


void _pow(int n){
    long long a = 0, b = 0, mod = 1'000'000'000'000'000'000;
    for(int i=0; i<n; i++){
        b*=2;
        a = 2 * a + 1;
        b += a / mod;
        a %= mod;
    }
    if(b>0) cout << b << a << '\n';
    else cout << a << '\n';
}


//start : 0 , mid:1, end:2
void moveBlock(int start, int end){
    cout << start+1 << ' ' << end+1 << '\n';
}


void hanoi(int n, int start, int mid, int end){
    if(n==0) return;
    hanoi(n-1, start, end, mid);
    //마지막꺼 옮기기
    moveBlock(start, end);
    hanoi(n-1, mid, start, end);
}

int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int n;
    cin >> n;
    _pow(n);

    if(n<=20) {
        hanoi(n, 0, 1, 2);
    }

    return 0;
}
반응형
반응형

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

 

1004번: 어린 왕자

입력의 첫 줄에는 테스트 케이스의 개수 T가 주어진다. 그 다음 줄부터 각각의 테스트케이스에 대해 첫째 줄에 출발점 (x1, y1)과 도착점 (x2, y2)이 주어진다. 두 번째 줄에는 행성계의 개수 n이 주

www.acmicpc.net

#include <bits/stdc++.h>
using namespace std;

int stx,sty, enx,eny;

bool inAndOut(int x, int y, int r){
    int startToCircleDist = (stx-x)*(stx-x) + (sty-y)*(sty-y);
    int endToCircleDist = (enx-x)*(enx-x) + (eny-y)*(eny-y);
    int R = r*r;

    if((startToCircleDist > R && endToCircleDist < R)||(startToCircleDist < R && endToCircleDist > R)) return true;
    return false;
}


int main() {
    ios::sync_with_stdio(0); cin.tie(0);

    int T;
    cin>> T;
    for(int t=0;t<T; t++){
        int n;
        cin >> stx >> sty >> enx >> eny >> n;

        int ans = 0;
        for(int i=0; i<n; i++){
            int x, y, r;
            cin >> x >> y >> r;
            if(inAndOut(x,y,r)) ans++;
        }
        cout << ans << '\n';
    }

    return 0;
}

 

반응형
반응형

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

 

2263번: 트리의 순회

첫째 줄에 n(1 ≤ n ≤ 100,000)이 주어진다. 다음 줄에는 인오더를 나타내는 n개의 자연수가 주어지고, 그 다음 줄에는 같은 식으로 포스트오더가 주어진다.

www.acmicpc.net

import java.util.Scanner;

class Tree {
    class Node{
        int data;
        Node left, right;
        Node(int data){
            this.data = data;
        }
    }
    Node root;
    static int pIndex = 0;

    public void buildTreeByInPost(int in[], int post[]){
        pIndex = post.length - 1;
        root = buildTreeByInPost(in ,post, 0, in.length-1);
    }

    private Node buildTreeByInPost(int in[], int post[], int start, int end){
        if(start > end) return null;
        Node node = new Node(post[pIndex--]);
        if(start==end) return node;
        int mid = search(in, start, end, node.data);

        node.right = buildTreeByInPost(in, post, mid+1, end);
        node.left = buildTreeByInPost(in, post, start, mid-1);
        return node;
    }

    private int search(int arr[], int start, int end, int value){
        int i;
        for(i=start; i<=end; i++){
            if(arr[i]==value) return i;
        }
        return i;
    }

    void printPreorder(Node node){
        if(node == null) return;
        System.out.print(node.data + " ");
        printPreorder(node.left);
        printPreorder(node.right);
    }
}

public class Main {
    public static void main(String args[]){
        int n;
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int[] in = new int[n];
        int[] post = new int[n];

        for(int i=0; i<n;i++){
            in[i] = sc.nextInt();
        }

        for(int i=0; i<n;i++){
            post[i] = sc.nextInt();
        }

        Tree tree = new Tree();
        tree.buildTreeByInPost(in, post);
        tree.printPreorder(tree.root);
    }
}

 

반응형

+ Recent posts