[백준] ATM (java) Greedy

2020-02-12

ATM (백준 > 11399 > Greedy)

문제 링크

문제설명

인하은행에는 ATM이 1대밖에 없다. 지금 이 ATM앞에 N명의 사람들이 줄을 서있다. 사람은 1번부터 N번까지 번호가 매겨져 있으며, i번 사람이 돈을 인출하는데 걸리는 시간은 Pi분이다.

사람들이 줄을 서는 순서에 따라서, 돈을 인출하는데 필요한 시간의 합이 달라지게 된다. 예를 들어, 총 5명이 있고, P1 = 3, P2 = 1, P3 = 4, P4 = 3, P5 = 2 인 경우를 생각해보자. [1, 2, 3, 4, 5] 순서로 줄을 선다면, 1번 사람은 3분만에 돈을 뽑을 수 있다. 2번 사람은 1번 사람이 돈을 뽑을 때 까지 기다려야 하기 때문에, 3+1 = 4분이 걸리게 된다. 3번 사람은 1번, 2번 사람이 돈을 뽑을 때까지 기다려야 하기 때문에, 총 3+1+4 = 8분이 필요하게 된다. 4번 사람은 3+1+4+3 = 11분, 5번 사람은 3+1+4+3+2 = 13분이 걸리게 된다. 이 경우에 각 사람이 돈을 인출하는데 필요한 시간의 합은 3+4+8+11+13 = 39분이 된다.

줄을 [2, 5, 1, 4, 3] 순서로 줄을 서면, 2번 사람은 1분만에, 5번 사람은 1+2 = 3분, 1번 사람은 1+2+3 = 6분, 4번 사람은 1+2+3+3 = 9분, 3번 사람은 1+2+3+3+4 = 13분이 걸리게 된다. 각 사람이 돈을 인출하는데 필요한 시간의 합은 1+3+6+9+13 = 32분이다. 이 방법보다 더 필요한 시간의 합을 최소로 만들 수는 없다.

줄을 서 있는 사람의 수 N과 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어졌을 때, 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)

출력

첫째 줄에 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 출력한다.

예제 입력 1

5
3 1 4 3 2

예제 출력 1

32


풀이

package Greedy;

import java.util.*;

import java.util.*;

public class beak_atm {
	
	//20 min
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
        
        ArrayList<Integer> list = new ArrayList<>();
        int n = sc.nextInt();
        for(int i=0;i<n;i++){
            list.add(sc.nextInt());
        }
		
        list.sort(null);
        
        int answer = 0; int k = 0;
        for(int i=0;i<list.size(); i++){
            answer = answer + list.get(i);
            k = k+ answer;
        }
        
        System.out.println(k);
	}
}


후기 (20min)

더 빨리 빨리 풀자. 쉬운 문제잖앗…!

Read More

[CodeUp] 성실한 개미 (java) Maze

2020-02-12

성실한 개미 (CodeUp > 1099 > Maze)

문제 링크

문제설명

영일이는 생명과학에 관심이 생겨 왕개미를 연구하고 있었다. 왕개미를 유심히 살펴보던 중 특별히 성실해 보이는 개미가 있었는데, 그 개미는 개미굴에서 나와 먹이까지 가장 빠른 길로 이동하는 것이었다. 개미는 오른쪽으로 움직이다가 벽을 만나면 아래쪽으로 움직여 가장 빠른 길로 움직였다. (오른쪽에 길이 나타나면 다시 오른쪽으로 움직인다.) 이에 호기심이 생긴 영일이는 그 개미를 미로 상자에 넣고 살펴보기 시작하였다. 미로 상자에 넣은 개미는 먹이를 찾았거나, 더 이상 움직일 수 없을 때까지 오른쪽 또는 아래쪽으로만 움직였다. 미로 상자의 구조가 0(갈 수 있는 곳), 1(벽 또는 장애물)로 주어지고, 먹이가 2로 주어질 때, 성실한 개미의 이동 경로를 예상해보자. 단, 맨 아래의 가장 오른쪽에 도착한 경우, 더 이상 움직일 수 없는 경우, 먹이를 찾은 경우에는 더이상 이동하지 않고 그 곳에 머무른다고 가정한다. 미로 상자의 테두리는 모두 벽으로 되어 있으며, 개미집은 반드시 (2, 2)에 존재하기 때문에 개미는 (2, 2)에서 출발한다.

img

입력


풀이

package Maze;

import java.util.Scanner;

class Codeup_성실한개미{
   
	//Maze
	//아니 이런문제로 한시간이나 쓰다니... 조건도 은근 많고...!
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        
        int maze[][] = new int[11][11];
        
        //한줄씩 입력받는법 까먹지말자
        for(int i=1;i<11; i++){
        		String a = sc.nextLine();
        		String b[] = a.split(" ");
                for(int j=0;j<10; j++)
                	maze[i][j+1]= Integer.parseInt(b[j]);
        }
        
        int x = 2;
        int y = 2;
  
        while(true){
        	
            if(maze[x][y]==2) {
            	maze[x][y]=9;
            	break;
            }
        	
            if(maze[x][y+1]==1){ //오른쪽이 벽
            	if(maze[x+1][y] ==1) // 밑에도 벽
            		break;
            	else // 밑이 벽이 아니면
            		x++;
            }
            else if(maze[x][y+1] !=1) { // 오른쪽이 벽이 아니면
            	y++;
            }
            
            if(maze[x][y]==2) {
            	maze[x][y]=9;
            	break;
            }
            
            maze[x][y]=9;
            
        }//while
        
        maze[2][2] = 9;
        
        
        
        for(int i=1; i<11; i++){
            for(int j=1; j<11; j ++){
                System.out.print(maze[i][j] + " ");
            }
            System.out.println("");
        }      
    
    }
}


후기 (1h)

헤매는 거 까지는 이해하겠는데 잔 조건들이 너무 많았다.

또한 여러 문자열을 통으로 받아서 이차원 배열에 집어넣는법.. 까먹지 말자. (여기서 너무 많이 헤맴)

Read More

[프로그래머스] 설탕 배달 (java) Math

2020-02-11

설탕 배달 (백준> 2839> Math)

문제 링크

문제설명

상근이는 요즘 설탕공장에서 설탕을 배달하고 있다. 상근이는 지금 사탕가게에 설탕을 정확하게 N킬로그램을 배달해야 한다. 설탕공장에서 만드는 설탕은 봉지에 담겨져 있다. 봉지는 3킬로그램 봉지와 5킬로그램 봉지가 있다.

상근이는 귀찮기 때문에, 최대한 적은 봉지를 들고 가려고 한다. 예를 들어, 18킬로그램 설탕을 배달해야 할 때, 3킬로그램 봉지 6개를 가져가도 되지만, 5킬로그램 3개와 3킬로그램 1개를 배달하면, 더 적은 개수의 봉지를 배달할 수 있다.

상근이가 설탕을 정확하게 N킬로그램 배달해야 할 때, 봉지 몇 개를 가져가면 되는지 그 수를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 N이 주어진다. (3 ≤ N ≤ 5000)

출력

상근이가 배달하는 봉지의 최소 개수를 출력한다. 만약, 정확하게 N킬로그램을 만들 수 없다면 -1을 출력한다.

예제 입력 1

18

예제 출력 1

4

풀이

package Math;

import java.util.*;

public class beak_설탕배달 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int n = sc.nextInt();
		int count = 0;
		
		//1.무조건 값에 -3을 하고  2.그 값이 5로 나누어지면 최소의 움직임  3.만약 break에 걸리지않고 0이하가 되면 -1
		while(true) {
			if(n%5==0) {
				//5로 나누어진다면 큰 수로 나눌 수 있는거니까 더 계산하지말고
				System.out.println(n/5 + count); //세어졌던 count에 몫을 더하면 값이 나온다
				break;
			}
			else if(n < 0) { //5로 나누어떨어지지않고  n이 2, 1..로 가면 -로가니까 break
				System.out.println(-1);
				break;
			}
			
			//3일때는 3-3 n=0이 되고 0%5는 0으로 count==1로 끝낼 수 있다. 놀랍...!
			n = n-3;
			count++;
			
		}		
	}
}


후기 (1h)

처음 풀려고 했던 방식

int arr[] = new int[n+1];		
Queue<Integer> qu = new LinkedList<>();
qu.add(n);

if(n%3 !=0 && n%5 !=0) {
	System.out.println(-1);
	return ;
}

while(!qu.isEmpty()) {
	int num = qu.poll();

	int a = num-5;
	int b = num-3;
	
	if(a >= 0 && arr[a]==0) {
		qu.add(a);
		arr[a] = arr[num] + 1;
	}
	if(b >=0 && arr[b]==0) {
		qu.add(b);
		arr[b] = arr[num] + 1;
	}
	
	
	if(a == 0) {
		System.out.println(arr[a]);				
		break;
	}
	if(b == 0) {
		System.out.println(arr[b]);
		break;
	}	
}

이 방법은 -1을 처리할 수 없었다…! 고로 다른 방법을 찾아 보고 익혔다!


tip

  1. 숫자로 푸는 문제들은 정말 수학문제처럼 정답이 떠오르지 않을 때가 많아 답답하지만… 그래도 더 노력하자


Read More

[백준] 계단 오르기 (java) Dynamic_programming

2020-02-11

계단 오르기 (백준> 2579> Dynamic_programming)

문제 링크

문제설명

계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. <그림 1>과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점수를 얻게 된다.

img

예를 들어 <그림 2>와 같이 시작점에서부터 첫 번째, 두 번째, 네 번째, 여섯 번째 계단을 밟아 도착점에 도달하면 총 점수는 10 + 20 + 25 + 20 = 75점이 된다.

img

계단 오르는 데는 다음과 같은 규칙이 있다.

  1. 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.
  2. 연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다.
  3. 마지막 도착 계단은 반드시 밟아야 한다.

따라서 첫 번째 계단을 밟고 이어 두 번째 계단이나, 세 번째 계단으로 오를 수 있다. 하지만, 첫 번째 계단을 밟고 이어 네 번째 계단으로 올라가거나, 첫 번째, 두 번째, 세 번째 계단을 연속해서 모두 밟을 수는 없다.

각 계단에 쓰여 있는 점수가 주어질 때 이 게임에서 얻을 수 있는 총 점수의 최댓값을 구하는 프로그램을 작성하시오.

입력

입력의 첫째 줄에 계단의 개수가 주어진다.

둘째 줄부터 한 줄에 하나씩 제일 아래에 놓인 계단부터 순서대로 각 계단에 쓰여 있는 점수가 주어진다. 계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10,000이하의 자연수이다.

출력

첫째 줄에 계단 오르기 게임에서 얻을 수 있는 총 점수의 최댓값을 출력한다.

예제 입력 1

6
10
20
15
25
10
20

예제 출력 1

75


풀이

package Dynamic_programming;

import java.util.*;

public class beak_계단오르기 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int n = sc.nextInt();
		
		int arr[] = new int[n+1]; 
		int dp[] = new int[n+1]; //계단이 가지는 최대값
		
		for(int i=1;i<=n;i++) 
			arr[i] = sc.nextInt();
		
		//배얼에 넣고 최댓값 구하기
		dp[1] = arr[1];
		dp[2] = arr[2] + dp[1];
		
		for(int i=3; i<=n;i++) {
			dp[i] = Math.max(arr[i] + dp[i-2], arr[i] + arr[i-1] + dp[i-3]);
		}
		
		System.out.println(dp[n]);
	}
}


후기 (1h 30min)

전에 한 번 풀었던 문제였음에도 너무 까마득한 기억이었고.. dp라는 것 밖에는..

또 답을 봐도 오랫동안 이해가 안갔다… 으아 똥멍청인가

arr[i] + arr[i-1] + dp[i-3] 이해가 안되면 이해하려고 노력이라도 해보잡


tip

  1. dp는 해도 안느는거같아.. 호호


Read More

[백준] 피보나치 함수 (java) Dynamic_programming

2020-02-11

피보나치 함수 (백준> 1003> Dynamic_programming)

문제 링크

문제설명

다음 소스는 N번째 피보나치 수를 구하는 C++ 함수이다.

fibonacci(3)을 호출하면 다음과 같은 일이 일어난다.

  • fibonacci(3)fibonacci(2)fibonacci(1) (첫 번째 호출)을 호출한다.
  • fibonacci(2)fibonacci(1) (두 번째 호출)과 fibonacci(0)을 호출한다.
  • 두 번째 호출한 fibonacci(1)은 1을 출력하고 1을 리턴한다.
  • fibonacci(0)은 0을 출력하고, 0을 리턴한다.
  • fibonacci(2)fibonacci(1)fibonacci(0)의 결과를 얻고, 1을 리턴한다.
  • 첫 번째 호출한 fibonacci(1)은 1을 출력하고, 1을 리턴한다.
  • fibonacci(3)fibonacci(2)fibonacci(1)의 결과를 얻고, 2를 리턴한다.

1은 2번 출력되고, 0은 1번 출력된다. N이 주어졌을 때, fibonacci(N)을 호출했을 때, 0과 1이 각각 몇 번 출력되는지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다.

각 테스트 케이스는 한 줄로 이루어져 있고, N이 주어진다. N은 40보다 작거나 같은 자연수 또는 0이다.

출력

각 테스트 케이스마다 0이 출력되는 횟수와 1이 출력되는 횟수를 공백으로 구분해서 출력한다.

예제 입력 1

3
0
1
3

예제 출력 1

1 0
0 1
1 2


풀이

package Dynamic_programming;

import java.util.*;

public class beak_피보나치함수 {

	//35min
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		
		for(int i=0;i<n;i++) {
			int a = sc.nextInt();
			
			if(a==0)
				System.out.println("1 0");
			else if(a==1)
				System.out.println("0 1");
			else {
				int arr[][] = new int[a+1][2];
				arr[0][0] = 1; arr[0][1] = 0;
				arr[1][0] = 0; arr[1][1] = 1;
				
				//f(5) a=5까지 구하고싶으면 j<=a까지로 해야하고 배열의 크기는 [a+1] 출력할때는 [a][0] + [a][1]
				for(int j=2; j<=a; j++) {
					arr[j][0] = arr[j-1][0] + arr[j-2][0];
					arr[j][1] = arr[j-1][1] + arr[j-2][1];
				}
				
				System.out.println(arr[a][0] +" " + arr[a][1]);
			}
		}//for	
	}
}


후기 (35min)

처음에 풀었던 방식은 당연히 시간초과…ㅎ

또한 dp[i] = dp[i-1] + dp[i-2] 방식이 상당히 많으므로 기저조건을 찾는 법을 익히고! 익혀둘 것!

Read More