반응형

문제 링크 :  https://algospot.com/judge/problem/read/TRIANGLEPATH

동적계획법을 이용하여 풀이하였습니다. dp를 처음접하는데 좋은 문제라 생각되네요


#include <cstdio>

#include <iostream>

#include <algorithm>

#include <string.h>

#include <stack>

#include <queue>

#include <vector>

#include <functional>


#define MAX 100

#define INF 0x7fffffff


using namespace std;

int n, t[MAX][MAX];

int dp[MAX][MAX];


int solve(int y, int x)

{

if(y==n-1)

return t[y][x];

int& ret=dp[y][x];

if(ret != -1)

return ret;

return ret = max(solve(y+1,x), solve(y+1,x+1)) + t[y][x];

}

int main(void)

{

int height;

scanf("%d",&n);

while(n--)

{

memset(dp,-1,sizeof(dp));

scanf("%d",&height);

for(int i=0;i<height;i++)

for(int j=0;j<i+1;j++)

scanf("%d",&t[i][j]);

cout<<solve(0,0)<<endl;

}

return 0;

}


반응형
반응형

문제 : https://www.acmicpc.net/problem/2698



아직 내공이 부족해서 한참 고민하고 겨우겨우 풀이한 문제였다.

핵심은 끝자리가 0일때와 1일때를 나누어 생각하는 것이고 n번째를 구하기 위해 n-1번째 값을 사용하기 위해 생각해 본 결과 점화식을 얻을 수 있었다. 또 점화식을 얻는데 중요한 힌트가 되었던 것은 문제 내에 식이 써있는 것도 많은 도움이 되었다.


dp[n][k][0] = dp[n-1][k][0] + dp[n-1][k][1]

dp[n][k][1] = dp[n-1][k][0] + dp[n-1][k-1][1]


소스코드

 //

//  main.cpp

//  Algorihm

//

//  Created by sw on 2018. 9. 10..

//  Copyright © 2018년 sw. All rights reserved.

//

#include <cstdio>

#include <string.h>

#include <iostream>

#include <algorithm>

#include <queue>

#define MAX 101

using namespace std;

int n,k;

int dp[MAX][MAX][2];

queue<int> q;

void solve(int n, int k){

    dp[1][0][0]=dp[1][0][1]=1;

    for(int i=2;i<=n;i++){

        for(int j=0;j<i;j++){

            dp[i][j][0] = dp[i-1][j][0]+dp[i-1][j][1];

            dp[i][j][1] = dp[i-1][j][0]+dp[i-1][j-1][1];

        }

    }

    q.push(dp[n][k][0]+dp[n][k][1]);

}

int main(int argc, const char * argv[]) {

    int tc;

    scanf("%d",&tc);

    while(tc--){

        scanf("%d %d", &n, &k);

        memset(dp,0,sizeof(dp));

        solve(n,k);

    }

    //출력

    while(!q.empty()){

        cout<<q.front()<<endl;

        q.pop();

    }

    return 0;

}


반응형

'Algorithm' 카테고리의 다른 글

[Algospot] PI 원주율 외우기  (0) 2018.09.19
[Algospot] TRIANGLEPATH 삼각형 위의 최대 경로  (0) 2018.09.17
[BOJ 2167] 2차원배열의 합 구하기  (0) 2018.09.07
[BOJ 11048] 다리놓기  (0) 2018.09.07
코딩인터뷰  (0) 2018.08.10
반응형

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



#include <iostream>

#define MAX 301

int N,M,K;

int dp[MAX][MAX];


using namespace std;

void getSum(){

int value;

cin>>N>>M;

for(int i=1;i<=N;i++){

for(int j=1;j<=M;j++){

cin>>value;

dp[i][j]=value + dp[i][j-1] + dp[i-1][j] - dp[i-1][j-1];

}

}

cin>>K;

while(K--){

int x1,y1,x2,y2;

cin>>x1>>y1>>x2>>y2;

cout<<dp[x2][y2] -(dp[x1-1][y2] + dp[x2][y1-1] - dp[x1-1][y1-1])<<endl;

}

}

int main(){

getSum();

return 0;


차근차근 생각하면 어렵지 않은 문제 

어렵다면 그림을 그려보자

dp[i][j]를 구할때 중복되는 값이 있다는 것을 인지한다면 쉽게 풀 수 있다.

반응형

'Algorithm' 카테고리의 다른 글

[Algospot] TRIANGLEPATH 삼각형 위의 최대 경로  (0) 2018.09.17
[BOJ 2698] 인접한 비트의 개수  (0) 2018.09.10
[BOJ 11048] 다리놓기  (0) 2018.09.07
코딩인터뷰  (0) 2018.08.10
깊이 우선 탐색(DFS, Depth First Search)  (0) 2018.08.08
반응형

문제

준규는 N×M 크기의 미로에 갇혀있다. 미로는 1×1크기의 방으로 나누어져 있고, 각 방에는 사탕이 놓여져 있다. 미로의 가장 왼쪽 윗 방은 (1, 1)이고, 가장 오른쪽 아랫 방은 (N, M)이다.

준규는 현재 (1, 1)에 있고, (N, M)으로 이동하려고 한다. 준규가 (r, c)에 있으면, (r+1, c), (r, c+1), (r+1, c+1)로 이동할 수 있고, 각 방을 방문할 때마다 방에 놓여져있는 사탕을 모두 가져갈 수 있다. 또, 미로 밖으로 나갈 수는 없다.

준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수의 최대값을 구하시오.

입력

첫째 줄에 미로의 크기 N, M이 주어진다. (1 ≤ N, M ≤ 1,000)

둘째 줄부터 N개 줄에는 총 M개의 숫자가 주어지며, r번째 줄의 c번째 수는 (r, c)에 놓여져 있는 사탕의 개수이다. 사탕의 개수는 0보다 크거나 같고, 100보다 작거나 같다.

출력

첫째 줄에 준규가 (N, M)으로 이동할 때, 가져올 수 있는 사탕 개수를 출력한다.

예제 입력 1 

3 4
1 2 3 4
0 0 0 5
9 8 7 6

예제 출력 1 

31

예제 입력 2 

3 3
1 0 0
0 1 0
0 0 1

예제 출력 2 

3

예제 입력 3 

4 3
1 2 3
6 5 4
7 8 9
12 11 10

예제 출력 3 

47







문제는 간단하다. 기본적인 DP문제이다. 유의할 점은 dp[i][j]를 구할때 대각선으로 가는 것은 고려하지 않아도 된다는 것이다. 왜냐하면 음수값을 입력하지 않기 때문이다. 즉 점화식을 구하면

dp[i][j]=max(dp[i-1][j],dp[i][j-1])+d[i][j]가 된다. 


 //

//  main.cpp

//  Algorihm

//

//  Created by sw on 2018. 9. 7..

//  Copyright © 2018년 sw. All rights reserved.

//


#include <iostream>

#include <algorithm>

#define MAX 1001

int N,M;

int dp[MAX][MAX];


using namespace std;


int move(int x, int y){

    int value;

    for(int i=1;i<=N;i++){

        for(int j=1;j<=M;j++){

            cin>>value;

            dp[i][j]=max(dp[i-1][j],dp[i][j-1])+value;

        }

    }

    return dp[x][y];

}

int main(int argc, const char * argv[]) {

    cin>>N>>M;

    cout<<move(N,M)<<endl;

    return 0;

}


반응형

'Algorithm' 카테고리의 다른 글

[BOJ 2698] 인접한 비트의 개수  (0) 2018.09.10
[BOJ 2167] 2차원배열의 합 구하기  (0) 2018.09.07
코딩인터뷰  (0) 2018.08.10
깊이 우선 탐색(DFS, Depth First Search)  (0) 2018.08.08
[백준 9507] Generations of Tribbles  (0) 2018.06.26
반응형

1.1 문자열에 포함된 문자들이 전부 유일한지를 검사하는 알고리즘을 구현하라. 다른 자료구조를 사용할 수 없는 상황이라면 어떻게 하겠는가?

//풀이(C++) 

bool isUnique(string* str){

if(str->length() > 256) 

return false;

bool check[256];

for(int i=0;i<str->length();i++){

int index=str->at(i);


if(check[index]==true)

return false;

else

check[index]=true;

}


return true;

}

sol) 문자열이 ASCII코드라고 가정할 때 문자는 총 256개이다. 즉 문자열의 길이가 256 이상이면 중복이 존재할 것이다. 이후 boolean형 배열을 정의해 문자열을 탐색하여 기존에 있던 문자면 false를 반환하도록 한다.


1.2 널 문자로 끝나는 문자열을 뒤집는 reverse(char* str)함수를 C나 C++로 구현하라.

//reverse함수 구현

//문자열 str포인터를 인자로 받아 역순으로 값을 바꿈

//풀이(C++)

void reverse(char *str)

{

char *end = str;

char temp;

if(str)

{

while(*end)

{

++end;

}

--end; //마지막 null값 제외

while(str<end)

{

temp=*str;

*str++ = *end;

*end-- = temp;

}

}

}

쉬운 문제이므로 pass!


1.3 문자열 두 개를 입력으로 받아 그중 하나가 다른 하나의 순열인지 판별하는 메서드를 작성하라.

        //순열 = 문자열 종류와 길이는 같고 배열된 순서는 다를 수 있음

//풀이(JAVA)

/*

* 가장 먼저 문자열의 길이를 비교한다.

* 이후 정렬을 통해 문자열 종류를 비교한다.

*/

public boolean isCheck(String str1, String str2)

{

if(str1.length() != str2.length())

return false;

return sort(str1).equals(sort(str2));

}

public String sort(String str)

{

char[] result=str.toCharArray();

java.util.Arrays.sort(result);

return new String(result);


1.4 주어진 문자열 내의 모든 공백을 '%20'으로 바꾸는 메소드를 작성하라. 문자열 끝에 추가로 필요한 문자들을 더할 수 있는 충분한 공간이 있다고 가정하라. 그리고 공백을 포함하는 문자열의 길이도 함 주어진다고 가정하라.

Ex) 입력 : "Mr John Smith"

     출력 : "Mr%20John%20Smith"

//풀이(C++)

void convert(char str[], int len)

{

int blank=0; //공백 개수

int strlen=len;

for(int i=0;i<len;i++){

if(str[i]==' ')

++blank;

}

strlen+=(blank*2); //2자리 증가

str[strlen]='\0';


for(int i=len-1;i>=0;i--){

if(str[i]==' '){

str[strlen-1]='0';

str[strlen-2]='2';

str[strlen-3]='%';

strlen-=3;

}

else

{

str[strlen-1]=str[i];

strlen--;

}

}

cout<<str;

}


반응형

'Algorithm' 카테고리의 다른 글

[BOJ 2167] 2차원배열의 합 구하기  (0) 2018.09.07
[BOJ 11048] 다리놓기  (0) 2018.09.07
깊이 우선 탐색(DFS, Depth First Search)  (0) 2018.08.08
[백준 9507] Generations of Tribbles  (0) 2018.06.26
[백준 6359] 만취한 상범  (0) 2018.06.25
반응형

 깊이 우선 탐색이라는 알고리즘에 대해 알아보려고 합니다. 일반적으로 DFS 알고리즘을 구현할때는 스택을 이용하고, 트리 혹은 그래프 같은 자료구조에서 데이터를 탐색할 때 사용하는 알고리즘 입니다. 나중에 알아볼 너비 우선 탐색이라는 비슷한 알고리즘이 있는데, 다음 게시물에서 다루도록 하겠습니다.

 깊이 우선 탐색 알고리즘은 한마디로 더 나아갈 길이 보이지 않을 만큼 깊게 들어가는 특징을 지니고 있으며, 더 깊게 들어갈 경로가 존재하지 않으면 이전의 위치로 돌아온 뒤 다른 경로를 선택해서 움직입니다.


(그래프를 첨부하고 싶은데 어떻게 첨부하는지 모르겠네요 ㅠㅠ)


연습장 꺼내신 후 직접 그려보시면 이해가 더 빠르실거에요...ㅎㅎㅎ


그래프를 간략하게 노드들만 나타내보도록 하겠습니다 각 노드간은 연결되어 있는 상태라고 가정할게요. 즉 각 Vertex들을 잇는 Edge는 모두 연결되어 있는 상태입니다!


 

 

 1

 

 

 

 2

 

 

 

 4

 

 

 

 

 8

 

 


 시작 Vertex(노드)는 1에서 부터 시작하겠습니다. 앞에서 언급했듯이 계속 탐색한 후 길이 없으면 되돌아 간 후 다른 경로를 선택하는 알고리즘 입니다.

 방문 순서는 1 -> 2 -> 4 -> 8 -> 5 -> 6 -> 3 -> 7 로 진행되겠죠. 그렇다면 여기서 이론은 끝! DFS 알고리즘을 직접 구현해보도록 하겠습니다. 먼저 코드로 구현하기 전에 Vertex간 관계를 나타내기 위해 인접행렬을 사용하겠습니다. 인접행렬은 그래프에서 각 정점의 인접관계를 나타내는 행렬입니다. (간단한 내용이니 궁금하시면 검색해보세요!)


※ 인접행렬


1

 0

1

1

0

0

0

0

0



C++로 구현한 단순 DFS 알고리즘 입니다.

#include <iostream>


int vertex; //정점 갯수

int map[30][30], visit[30]; // map - 상호간 연결을 나타냄 

// visit - 방문 여부

void DFS(int t_vertex);

using namespace std;


int main()

{

int sVertex; // Start Vertex

int v1, v2;


cin>>vertex>>sVertex;


while(true)

{

cin>>v1>>v2;

if(v1 == -1 && v2 == -1) //무한루프 방지

break;

map[v1][v2] = map[v2][v1] = 1; // vertex 상호간 연결

}

DFS(sVertex);


return 0;

}


void DFS(int t_vertex)

{

visit[t_vertex] = 1; // visit vertex

for(int i=1; i<=vertex; i++){

if(map[t_vertex][i] == 1 && !visit[i])

{

cout<<t_vertex<<"에서 "<<i<<"로 이동합니다"<<endl;

DFS(i);

}

}

















반응형

'Algorithm' 카테고리의 다른 글

[BOJ 11048] 다리놓기  (0) 2018.09.07
코딩인터뷰  (0) 2018.08.10
[백준 9507] Generations of Tribbles  (0) 2018.06.26
[백준 6359] 만취한 상범  (0) 2018.06.25
[백준 1932] 숫자삼각형  (0) 2018.03.30
반응형

문제

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


문제

꿍은 군대에서 진짜 할짓이 없다. 그래서 꿍만의 피보나치를 만들어보려고 한다. 기존의 피보나치는 너무 단순해서 꿍은 좀더 복잡한 피보나치를 만들어보고자 한다. 그래서 다음과 같은 피보나치를 만들었다. 꿍만의 피보나치 함수가 koong(n)이라고 할 때,

n < 2 :                         1
n = 2 :                         2
n = 3 :                         4
n > 3 : koong(n − 1) + koong(n − 2) + koong(n − 3) + koong(n − 4)

이다.

여러분도 꿍 피보나치를 구해보아라.

 

입력

입력의 첫번째 줄을 테스트케이스의 개수 t (0 < t < 69)가 주어진다. 다음 t줄에는 몇번째 피보나치를 구해야하는지를 나타내는 n(0 ≤ n ≤ 67)이 주어진다.

출력

각 테스트케이스에 대해, 각 줄에 꿍 피보나치값을 출력하라.

예제 입력 1 

8
0
1
2
3
4
5
30
67

예제 출력 1 

1
1
2
4
8
15
201061985
7057305768232953720



















이 문제를 틀렸다면 이유는 알고리즘적 문제가 아니라 자료형 선언일 것이다. 아마 int형으로 선언하지 않았을까 한다. DP문제로 메모리제이션 기법을 사용하여 풀이 하였다.

문제 난이도가 쉬우므로 자세한 설명은 생략하기로 한다. 피보나치 형식대로 함수를 구현해 주면 된다.


소스코드

//

//  main.cpp

//  DP

//

//  Created by seungwoo on 2018. 06. 28

//  Copyright © 2018년 seungwoo. All rights reserved.

//


#include <iostream>

#include <algorithm>


using namespace std;


long long fibo(int n);


int main()

{

int T,n;

cin>>T;

while(T>0)

{

T--;

cin>>n;

cout<<fibo(n)<<endl;

}

return 0;

}

long long fibo(int n)

{

static long long dp[68]={0};

if(dp[n]!=0) return dp[n];

if(n==0 || n==1) return 1;

else if(n==2) return 2;

else if(n==3) return 4;

return dp[n]=fibo(n-1) + fibo(n-2) + fibo(n-3) + fibo(n-4);



반응형

'Algorithm' 카테고리의 다른 글

코딩인터뷰  (0) 2018.08.10
깊이 우선 탐색(DFS, Depth First Search)  (0) 2018.08.08
[백준 6359] 만취한 상범  (0) 2018.06.25
[백준 1932] 숫자삼각형  (0) 2018.03.30
[백준 1149] RGB거리  (0) 2018.03.29
반응형

문제

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



문제

서강대학교 곤자가 기숙사의 지하에는 n개의 방이 일렬로 늘어선 감옥이 있다. 각 방에는 벌점을 많이 받은 학생들이 구금되어있다.

그러던 어느날, 감옥 간수인 상범이는 지루한 나머지 정신나간 게임을 하기로 결정했다. 게임의 첫 번째 라운드에서 상범이는 위스키를 한 잔 들이키고, 달려가며 감옥을 한 개씩 모두 연다. 그 다음 라운드에서는 2, 4, 6, ... 번 방을 다시 잠그고, 세 번째 라운드에서는 3, 6, 9, ... 번 방이 열려있으면 잠그고, 잠겨있다면 연다. 같은 방식으로 n번의 라운드를 진행한 이후, 상범이는 위스키의 마지막 병을 마시고 쓰러져 잠든다.

구금되어있는 몇 명(어쩌면 0명)의 학생들은 자신의 방을 잠그지 않은 채 상범이가 쓰러져버렸단 것을 깨닫고 즉시 도망친다.

방의 개수가 주어졌을 때, 몇 명의 학생들이 도주할 수 있는지 알아보자.

입력

입력의 첫 번째 줄에는 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄에 한 개씩 방의 개수 n(5≤n≤100)이 주어진다.

출력

한 줄에 한 개씩 각 테스트 케이스의 답, 즉 몇 명이 탈출할 수 있는지를 출력한다.

예제 입력 1 

2
5
100

예제 출력 1 

2
10







   



문제 풀이

테스트 케이스는 5이상 100이하이다.

즉 방이 최소 5개 존재한다는 것이다. 처음에 문제를 이해할 때는 짝수 번째는 2의 배수 홀수 번째는 3의 배수로 풀이하다가 잘못된 것을 알고

2번째는 2의 배수, 3번째는 3의 배수 4번째는 4의 배수, n번째는 n의 배수임을 깨닫게 되었다.


n = 5인 경우 (1 = open / 0 = close)


  1 

 1

 1

0

 1

 1

0


위 표를 보면 규칙이 각 라운드 마다 열거나 닫는 방 번호는 라운드의 배수임을 알 수 있다. 

즉, 방번호 % 라운드 == 0 인 경우 열린 문은 닫고, 닫힌 문은 열면 되는 간단한 문제이다.

if문을 사용해서 방번호 %라운드 ==0 조건을 사용해도 되지만 조건을 조금 더 간단하게 하는 방법이 있다.

해당 라운드의 배수인 방이 열려있으면 닫고 닫혀있으면 여는 방법이다.

충분히 생각해보고 소스코드를 참고하자


소스코드

//

//  main.cpp

//  Algorithm

//

//  Created by sw on 2018. 6. 25..

//  Copyright © 2018년 sw. All rights reserved.

//


#include <iostream>

#include <algorithm>


using namespace std;

int main(int argc, const char * argv[]) {

    // insert code here...

    int testcase, room;

    cin>>testcase;

    while(testcase>0){

        testcase--;

        cin>>room;

        int dp[101] = {0};  //dp 저장 변수(테스트케이스마다 초기화를 위해 while문 안에 선언)

        for(int i=1;i<=room;i++){

            for(int j=1; i*j<=room; j++){

                if(dp[i*j]==1) dp[i*j]=0;

                else dp[i*j]=1;

            }

        }

        for(int i=1; i<=room; i++){

            dp[0] += dp[i]; //dp[0]를 count로 사용

                            //for문을 사용하고 싶지 않다면 위쪽 if문에서 dp[0]값을 더하거나 빼주면 됨.

        }

        cout<<dp[0]<<endl;  //문이 열린 갯수 출력

    }

    return 0;

} 



반응형

'Algorithm' 카테고리의 다른 글

깊이 우선 탐색(DFS, Depth First Search)  (0) 2018.08.08
[백준 9507] Generations of Tribbles  (0) 2018.06.26
[백준 1932] 숫자삼각형  (0) 2018.03.30
[백준 1149] RGB거리  (0) 2018.03.29
[백준 1003] 피보나치 함수  (0) 2018.03.28
반응형

문제

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


        7
      3   8
    8   1   0
  2   7   4   4
4   5   2   6   5

위 그림은 크기가 5인 숫자 삼각형의 한 모습이다.

맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다.

삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 숫자는 모두 정수이며, 범위는 0 이상 9999 이하이다.

입력

첫째 줄에 삼각형의 크기 n(1 ≤ n ≤ 500)이 주어지고, 둘째 줄부터 n+1줄까지 숫자 삼각형이 주어진다.

출력

첫째 줄에는 최대가 되는 합을 출력한다.

입력

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5


출력

30


먼저 N을 입력받고 이차원배열에 숫자삼각형을 입력한다.

그리고 나서 윗층과 누적할 이차원배열이 필요하다. 크기는 숫자삼각형 입력받은 것과 동일하며 

두 번째줄부터 윗줄과 더하고 그 누적값을 가지고 있어야한다.

맨 왼쪽일 경우, 맨 오른쪽일 경우, 중간에 있을 경우가 있다.

여기서 맨 왼쪽, 오른쪽은 상관없지만 중간에 있을 경우 가장 큰 것을 찾아야 한다.

그러면 중간 값은 자기보다 위 줄의 좌, 우에서 큰 값을 찾아야한다.

즉 자신의 위치에서 대각선 , 우의 최대값을 가져오면 되는 문제이다.


소스

//

//  main.cpp

//  DP

//

//  Created by seungwoo on 2018. 3. 30..

//  Copyright © 2018년 seungwoo. All rights reserved.

//


#include <iostream>

#include <algorithm>

using namespace std;


int dp[502][502];

int a[502][502];

int main()

{

    int n;

    

    cin>>n;

    

    for(int i=1; i<=n; i++)

    {

        for(int j=1; j<=i; j++)

            cin>>a[i][j];

    }

    

    for(int i=1; i<=n; i++)

    {

        for(int j=1; j<=i; j++)

            dp[i][j] = a[i][j] +  max(dp[i-1][j],dp[i-1][j-1]);

    }

    int res = 0;

    for (int i = 1; i <= n; i++)

        res = max(res, dp[n][i]);

    cout<<res;

    return 0;

}


 




반응형

'Algorithm' 카테고리의 다른 글

[백준 9507] Generations of Tribbles  (0) 2018.06.26
[백준 6359] 만취한 상범  (0) 2018.06.25
[백준 1149] RGB거리  (0) 2018.03.29
[백준 1003] 피보나치 함수  (0) 2018.03.28
[백준 9095] 1,2,3 더하기  (0) 2018.03.27
반응형

문제

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



RGB거리에 사는 사람들은 집을 빨강, 초록, 파랑중에 하나로 칠하려고 한다. 또한, 그들은 모든 이웃은 같은 색으로 칠할 수 없다는 규칙도 정했다. 집 i의 이웃은 집 i-1과 집 i+1이다. 처음 집과 마지막 집은 이웃이 아니다.

각 집을 빨강으로 칠할 때 드는 비용, 초록으로 칠할 때 드는 비용, 파랑으로 드는 비용이 주어질 때, 모든 집을 칠할 때 드는 비용의 최솟값을 구하는 프로그램을 작성하시오.


입력

첫째 줄에 집의 수 N이 주어진다. N은 1,000보다 작거나 같다. 둘째 줄부터 N개의 줄에 각 집을 빨강으로 칠할 때, 초록으로 칠할 때, 파랑으로 칠할 때 드는 비용이 주어진다. 비용은 1,000보다 작거나 같은 자연수이다.


출력

첫째 줄에 모든 집을 칠할 때 드는 비용의 최솟값을 출력한다.


예제 입력

3
26 40 83
49 60 57
13 89 99


예제 출력

96


사실 알고리즘적 요소보다 문제 이해가 어려웠다.

문제 이해만 빠르고 확실하게 한다면 어려움없이 풀 수 있는 문제다.


만약 빨간집으로 시작했다면 2번째 집은 초록 or 파랑 이여만 한다.

즉 dp[0][1] (빨간색으로 칠했을때) = min(dp[1][i-1], dp[2][i-1])(전 집에서 초록색을 칠했을떄의 최소비용과 파란색으로 칠했을 떄의 최소비용 중 최소값) + r_cost (현재 i를 빨간색으로 칠했을때의 비용)

dp[1][1] (초록색으로 칠했을때) = min(dp[0][i-1], dp[1][i-1])(전 집에서 빨간색을 칠했을떄의 최소비용과 파란색으로 칠했을 떄의 최소비용 중 최소값) + g_cost (현재 i를 초록색으로 칠했을때의 비용)

dp[2][1] (파란색으로 칠했을때) = min(dp[0][i-1], dp[1][i-1])(전 집에서 빨간색을 칠했을떄의 최소비용과 초록색으로 칠했을 떄의 최소비용 중 최소값) + b_cost (현재 i를 파란색으로 칠했을때의 비용)


와 같은 식으로 진행되는 것을 알 수 있다.


이와 같은 식으로 모든 비용을 구한 이후 최소값을 출력해주는 알고리즘이다.



소스


//

//  main.cpp

//  DP

//

//  Created by seungwoo on 2018. 3. 29..

//  Copyright © 2018년 seungwoo. All rights reserved.

//


#include <iostream>

#include <algorithm>


using namespace std;


int main(int argc, const char * argv[]) {

    int house;

    int result;

    int cost[3][1001]={0};

    cin>>house;

    for(int i=1; i<=house; i++){

        int r_cost, g_cost, b_cost;

        cin>>r_cost>>g_cost>>b_cost;

        cost[0][i] = min(cost[1][i-1] , cost[2][i-1]) + r_cost;

        cost[1][i] = min(cost[0][i-1] , cost[2][i-1]) + g_cost;

        cost[2][i] = min(cost[0][i-1] , cost[1][i-1]) + b_cost;

    }

    result = min(cost[0][house], min(cost[1][house],cost[2][house]));

    cout<<result;

    return 0;

} 


반응형

'Algorithm' 카테고리의 다른 글

[백준 9507] Generations of Tribbles  (0) 2018.06.26
[백준 6359] 만취한 상범  (0) 2018.06.25
[백준 1932] 숫자삼각형  (0) 2018.03.30
[백준 1003] 피보나치 함수  (0) 2018.03.28
[백준 9095] 1,2,3 더하기  (0) 2018.03.27

+ Recent posts