반응형

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

 

1949번: 우수 마을

N개의 마을로 이루어진 나라가 있다. 편의상 마을에는 1부터 N까지 번호가 붙어 있다고 하자. 이 나라는 트리(Tree) 구조로 이루어져 있다. 즉 마을과 마을 사이를 직접 잇는 N-1개의 길이 있으며,

www.acmicpc.net

1. 문제설명

인접한 노드 두개가 우수마을이 되면 안된다.

그리고 자신이 우수마을이 아니라면 인접한 노드 중 적어도 하나가 우수마을이 되어야한다.

 

문제를 해결하기 위해

노드를 재귀적으로 탐색해야한다.

현재 노드가 우수마을인 경우와 우수마을이 아닌 경우를 나눈다.

 

그리고 현재 노드가 우수마을인 경우에는 다음 노드는 무조건 우수마을이면 안된다.

현재 노드가 우수마을이 아닌 경우에는 다음 노드는 우수마을이거나 우수마을이 아닐 수 있다.

 

이 때

현재 우수마을이 아닌데 다음 마을도 우수마을이 아닌 경우 문제가 생길 수 있다고 생각했다.

예를 들어 세개의 노드가 다 우수마을이 아닌 경우라면 문제의 조건에 맞지 않다.

하지만 다음 코드와 같이 재귀적으로 탐색하면서 최댓값을 계속 넘겨주다보면

모든 마을이 우수마을이 아닌 경우는 남지 않아서 괜찮다.

 

최댓값만 남기기 때문에 모든 마을이 우수마을이 아닌 경우는 살아남을 수 없다.

 

 


 

2.문제풀이코드 C++

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

int N, people[MX], dp[MX][2];
bool vis[MX];
vector<int> adj[MX];

void DFS(int node){
    dp[node][0] = 0;
    dp[node][1] = people[node];
    vis[node] = 1;

    for(int i=0; i<adj[node].size(); i++){
        int nx = adj[node][i];
        if(vis[nx]) continue;

        DFS(nx);
        dp[node][0] += max(dp[nx][0], dp[nx][1]);
        dp[node][1] += dp[nx][0];
    }
}


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

    cin >> N;
    for(int i=1; i<=N; i++){
        cin >> people[i];
    }

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

    DFS(1);
    cout << max(dp[1][0], dp[1][1]) << '\n';
    return 0;
}
반응형
반응형

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;
}
반응형
반응형

레트로핏 인터페이스

package com.example.unsplash_app_tutorial.retrofit

import com.example.unsplash_app_tutorial.utils.API
import com.google.gson.JsonElement
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query

interface IRetrofit {
    // https://www.unsplash.com/search/photos?query=""

    @GET(API.SEARCH_PHOTOS)
    fun searchPhotos(@Query("query") searchTerm: String) : Call<JsonElement>

    @GET(API.SEARCH_USERS)
    fun searchUsers(@Query("query") searchTerm: String) : Call<JsonElement>
}

 

RetrofitClient.kt

package com.example.unsplash_app_tutorial.retrofit

import android.util.Log
import com.example.unsplash_app_tutorial.utils.API
import com.example.unsplash_app_tutorial.utils.Constants.TAG
import com.example.unsplash_app_tutorial.utils.isJsonArray
import com.example.unsplash_app_tutorial.utils.isJsonObject
import com.google.gson.JsonObject
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.Exception

// 싱글턴
object RetrofitClient {
    // 레트로핏 클라이언트 선언

    private var retrofitClient: Retrofit? = null

    // 레트로핏 클라이언트 가져오기
    fun getClient(baseUrl: String): Retrofit? {
        Log.d(TAG, "RetrofitClient - getClient() called")

        // okhttp 인스턴스 생성
        val client = OkHttpClient.Builder()

        // 로그를 찍기 위해 로깅 인터셉터 추가
        val loggingInterceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
            override fun log(message: String) {
//                Log.d(TAG, "RetrofitClient - log() called / message: $message")

                when {
                    message.isJsonObject() ->
                        Log.d(TAG, JSONObject(message).toString(4))
                    message.isJsonArray() ->
                        Log.d(TAG, JSONObject(message).toString(4))
                    else -> {
                        try {
                            Log.d(TAG, JSONObject(message).toString(4))
                        } catch (e: Exception) {
                            Log.d(TAG, message)
                        }
                    }
                }
            }
        })

        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

        // 위에서 설정한 로깅 인터셉터를 okhttp 클라이언트에 추가한다.
        client.addInterceptor(loggingInterceptor)

        // 기본 파라미터 인터셉터 설정
        val baseParameterInterceptor: Interceptor = (object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                Log.d(TAG, "RetrofitClient - intercept() called")
                // 오리지널 리퀘스트
                val originalRequest = chain.request()

                // 쿼리 파라미터 추가하기
                val addedUrl =
                    originalRequest.url.newBuilder().addQueryParameter("client_id", API.CLIENT_ID)
                        .build()

                val finalRequest = originalRequest.newBuilder()
                    .url(addedUrl)
                    .method(originalRequest.method, originalRequest.body)
                    .build()
                return chain.proceed(finalRequest)
            }
        })

        // 위에서 설정한 기본 파라미터 인터셉터를 okhttp 클라이언트에 추가한다.
        client.addInterceptor(baseParameterInterceptor)
        
        // 레트로핏 빌더를 통해 인스턴스 생성
        if (retrofitClient == null) {
            retrofitClient = Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                // 위에서 설정한 클라이언트로 레트로핏 클라이언트를 설정한다.
                .client(client.build())
                .build()
        }
        return retrofitClient
    }
}

 

RetrofitManager

package com.example.unsplash_app_tutorial.retrofit

import android.util.Log
import com.example.unsplash_app_tutorial.utils.API
import com.example.unsplash_app_tutorial.utils.Constants.TAG
import com.example.unsplash_app_tutorial.utils.isJsonArray
import com.example.unsplash_app_tutorial.utils.isJsonObject
import com.google.gson.JsonObject
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.Exception
import java.util.concurrent.TimeUnit

// 싱글턴
object RetrofitClient {
    // 레트로핏 클라이언트 선언

    private var retrofitClient: Retrofit? = null

    // 레트로핏 클라이언트 가져오기
    fun getClient(baseUrl: String): Retrofit? {
        Log.d(TAG, "RetrofitClient - getClient() called")

        // okhttp 인스턴스 생성
        val client = OkHttpClient.Builder()

        // 로그를 찍기 위해 로깅 인터셉터 추가
        val loggingInterceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
            override fun log(message: String) {
//                Log.d(TAG, "RetrofitClient - log() called / message: $message")

                when {
                    message.isJsonObject() ->
                        Log.d(TAG, JSONObject(message).toString(4))
                    message.isJsonArray() ->
                        Log.d(TAG, JSONObject(message).toString(4))
                    else -> {
                        try {
                            Log.d(TAG, JSONObject(message).toString(4))
                        } catch (e: Exception) {
                            Log.d(TAG, message)
                        }
                    }
                }
            }
        })

        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

        // 위에서 설정한 로깅 인터셉터를 okhttp 클라이언트에 추가한다.
        client.addInterceptor(loggingInterceptor)

        // 기본 파라미터 인터셉터 설정
        val baseParameterInterceptor: Interceptor = (object : Interceptor {
            override fun intercept(chain: Interceptor.Chain): Response {
                Log.d(TAG, "RetrofitClient - intercept() called")
                // 오리지널 리퀘스트
                val originalRequest = chain.request()

                // 쿼리 파라미터 추가하기
                val addedUrl =
                    originalRequest.url.newBuilder().addQueryParameter("client_id", API.CLIENT_ID)
                        .build()

                val finalRequest = originalRequest.newBuilder()
                    .url(addedUrl)
                    .method(originalRequest.method, originalRequest.body)
                    .build()
                return chain.proceed(finalRequest)
            }
        })

        // 위에서 설정한 기본 파라미터 인터셉터를 okhttp 클라이언트에 추가한다.
        client.addInterceptor(baseParameterInterceptor)

        // 커넥션 타임 아웃
        client.connectTimeout(10, TimeUnit.SECONDS)
        client.readTimeout(10, TimeUnit.SECONDS)
        client.writeTimeout(10, TimeUnit.SECONDS)
        client.retryOnConnectionFailure(true)

        // 레트로핏 빌더를 통해 인스턴스 생성
        if (retrofitClient == null) {
            retrofitClient = Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                // 위에서 설정한 클라이언트로 레트로핏 클라이언트를 설정한다.
                .client(client.build())
                .build()
        }
        return retrofitClient
    }
}

 

반응형
반응형

MainActivity.kt

package com.example.mysingletonpractice

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log

class MainActivity : AppCompatActivity() {
    val TAG: String = "로그"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        Log.d(TAG, "MainActivity - onCreate() called")

        val myNormalClass_1 = MyNormalClass()
        val myNormalClass_2 = MyNormalClass()
        
        Log.d(TAG, "MainActivity myNormalClass_1 : $myNormalClass_1")
        Log.d(TAG, "MainActivity myNormalClass_2 : $myNormalClass_2")

        val mySingleTonClass_1 = MySingletonClass
        val mySingleTonClass_2 = MySingletonClass

        Log.d(TAG, "MainActivity - val mySingleTonClass_1 = $mySingleTonClass_1")
        Log.d(TAG, "MainActivity - val mySingleTonClass_2 = $mySingleTonClass_2")
        
        val mySQLOpenHelper_1 = MySQLOpenHelper(this)
        val mySQLOpenHelper_2 = MySQLOpenHelper(this)
        
        Log.d(TAG, "MainActivity - mySQLOpenHelper_1 : $mySQLOpenHelper_1")
        Log.d(TAG, "MainActivity - mySQLOpenHelper_2 : $mySQLOpenHelper_2")



        val MySQLOpenHelperSingleton_1 = MySQLOpenHelperSingleton.getInstance(this)
        val MySQLOpenHelperSingleton_2 = MySQLOpenHelperSingleton.getInstance(this)

        Log.d(TAG, "MainActivity - MySQLOpenHelperSingleton_1 : $MySQLOpenHelperSingleton_1")
        Log.d(TAG, "MainActivity - MySQLOpenHelperSingleton_2 : $MySQLOpenHelperSingleton_2")


    }
}

 

MySQLOpenHelperSingleton

package com.example.mysingletonpractice

import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper

class MySQLOpenHelperSingleton private constructor(context: Context) : SQLiteOpenHelper(context, "MyDB", null, 1) {
    val TAG = "MySQLOpenHelperSingleton"

    companion object{
        // 자기 자신 변수 선언
        @Volatile private var instance: MySQLOpenHelperSingleton? = null

        // 자기 자신 가져오기
        fun getInstance(context: Context) : MySQLOpenHelperSingleton =
            instance ?: synchronized(this){
                instance ?: MySQLOpenHelperSingleton(context).also{
                    instance = it
                }
            }
    }


    override fun onCreate(p0: SQLiteDatabase?) {
        TODO("Not yet implemented")
    }

    override fun onUpgrade(p0: SQLiteDatabase?, p1: Int, p2: Int) {
        TODO("Not yet implemented")
    }


}

 

반응형
반응형

lottie 활용해서 좋아요 버튼 만들기

 

Lottie Docs

 

http://airbnb.io/lottie/#/android?id=animation-listeners 

 

Lottie Docs

 

airbnb.io

 

좋아요 애니메이션 json 파일

https://lottiefiles.com/89777-like

 

 

 

lottie를 활용하려면 우선 build.gradle에 dependency에 lottie를 추가해주어야 한다.

dependencies {
    implementation "com.airbnb.android:lottie:5.2.0"
}

 

그리고 app 디렉토리에 assets 폴더를 만들고

다운로드 받은 lottie json 파일을 추가한다.

그리고 추가할 xml 파일에 LottieAnimationView를 추가하고

lottie_fileName에 다운로드 받은 로티 파일의 이름을 추가하면 xml에 로티파일을 추가할 수 있다.

 

 

 

로티 애니메이션을 커스텀 하려면 다음과 같은 방식으로 설정할 수 있다.

ofFloat는 애니메이션 전체의 어떤 부분을 보여줄 것인지 정할 수 있고

setDuration은 정한 부분을 몇초 동안 보여줄 것인지 정할 수 있다.

1초는 1000이다.

val animator = ValueAnimator.ofFloat(0f, 0.5f).setDuration(1000)
animator.addUpdateListener { animation : ValueAnimator ->
    like_btn.setProgress(
        animation.getAnimatedValue() as Float
    )
}
animator.start()

 

 

 

전체코드

 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    tools:context=".MainActivity">

    <com.airbnb.lottie.LottieAnimationView
        android:id="@+id/like_btn"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:background="@android:color/white"
        app:lottie_autoPlay="false"
        app:lottie_fileName="like.json"
        app:lottie_loop="false" />
</RelativeLayout>

 

 

MainActivity.kt

package com.example.lottieanimationtutorial

import android.animation.ValueAnimator
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import com.example.lottieanimationtutorial.databinding.ActivityMainBinding
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    val TAG = "MainActivity"

    var isLiked: Boolean = false
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        isLiked = false
        //좋아요 버튼에 클릭 리스너를 달아준다.
        like_btn.setOnClickListener {
            if(isLiked == false){
                val animator = ValueAnimator.ofFloat(0f, 0.5f).setDuration(1000)
                animator.addUpdateListener { animation : ValueAnimator ->
                    like_btn.setProgress(
                        animation.getAnimatedValue() as Float
                    )
                }
                animator.start()
                isLiked = true
            }else{ // 좋아요 상태일 때
                val animator = ValueAnimator.ofFloat(0.5f, 1f).setDuration(1000)
                animator.addUpdateListener { animation : ValueAnimator ->
                    like_btn.setProgress(
                        animation.getAnimatedValue() as Float
                    )
                }
                animator.start()
                isLiked = false
            }
        }

    }
}
반응형
반응형

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;
}

 

반응형
반응형

안드로이드 레이아웃 종류

안드로이드에서 자주 쓰는 레이아웃은 크게 3개가 존재한다.

LinearLayout, RelativeLayout,  ConstraintLayout이 있다.

 

LinearLayout은 horizontal이나 vertical 설정으로 편하게 레이아웃을 구성할 수 있다.

weightSum을 이용하면 웹의 css에서 flex와 같은 역할을 할 수 있다.

 

RelativeLayout은 뷰 id를 통해서 상대적 위치를 기준으로 뷰의 위치를 정해줄 수 있다.

또한 RelativeLayout을 이용하면 뷰를 겹쳐서 둘 수 있다.

 

ConstraintLayout은 앵커를 3개 두어 위치를 유동적으로 설정할 수 있다.

 

 

1. LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="horizontal"
    android:weightSum="3"
    android:gravity="center_vertical"
    >

    <View
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="#FF0000"
        />
    <View
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="#FFF200"
        />
    <View
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="50dp"
        android:background="#000DFF"
        />


</LinearLayout>

 

2. RelativeLayout

 

RelativeLayout

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RelativeLayout">

    <View
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:background="#FF8F00"
        />


    <View
        android:id="@+id/blue_view"
        android:layout_alignParentLeft="true"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/design_default_color_primary"
        />

    <View
        android:id="@+id/green_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#FD62FF00"
        android:layout_toRightOf="@+id/blue_view"
        />

</RelativeLayout>

 

 

3. ConstraintLayout

 

ConstraintLayout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ConstraintLayout">

    <View
        android:id="@+id/orange_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#F9A825"
        />
    <View
        android:id="@+id/blue_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toBottomOf="@id/orange_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#1984FF"
        />

    <View
        android:id="@+id/pink_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#FD18F2"
        app:layout_constraintTop_toBottomOf="@id/blue_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />

    <View
        android:id="@+id/yellow_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#FFF200"
        app:layout_constraintTop_toBottomOf="@id/pink_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />
    <View
        android:id="@+id/green_view"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#27FD18"
        app:layout_constraintTop_toBottomOf="@id/yellow_view"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>
반응형
반응형

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;
}
반응형

+ Recent posts