[문제링크]

 

16987번: 계란으로 계란치기

원래 프로그래머의 기본 소양은 팔굽혀펴기를 단 한 개도 할 수 없는 것이라고 하지만 인범이는 3대 500을 넘기는 몇 안되는 프로그래머 중 한 명이다. 인범이는 BOJ에서 틀린 제출을 할 때마다 턱

www.acmicpc.net

 

0. 내구도/데미지 값을 고려해서 가능한 많은 계란을 깨는 문제

 

1. 재귀를 사용해서 모든 경우의 수를 진행한다

  • 현재 계란이 깨지지 않았다면, 이걸로 다른 깨지지 않은 계란을 친다
  • 깨졌다면, 그냥 넘어간다
  • 다음번 계란으로 넘어가서 반복한다
  • 모든 계란에 대해 시도했다면, 종료하고 깬 계란 수를 관리한다
  • 계산 편의, 효율을 위해 깨진 계란의 수를 인자로 관리한다

 

2. 위 과정에서 나온 값들 중 최댓값을 저장, 출력

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int cnt = pint(br.readLine());
		int[][]egg = new int[cnt][2];
		
		for(int i=0; i<cnt; i++) {
			StringTokenizer st = new StringTokenizer(br.readLine(), " ");
			int S = pint(st.nextToken());
			int W = pint(st.nextToken());
			egg[i][0]=S;
			egg[i][1]=W;
		}
		
		System.out.println(rec(egg, 0, 0));
	}
	
	static int rec(int[][]egg, int curEgg, int breaked) {
		if(curEgg>=egg.length) {
			return breaked;
		}
		
		if(egg[curEgg][0]<=0) {
			return rec(egg, curEgg+1, breaked);
		}
		
		int ans=breaked;
		for(int i=0; i<egg.length; i++) {
			if(egg[i][0]<=0 || i==curEgg)continue;
			
			egg[curEgg][0]-=egg[i][1];
			egg[i][0]-=egg[curEgg][1];
			
			int tmpBreaked=0;
			tmpBreaked+= egg[curEgg][0]<=0?1:0;
			tmpBreaked+= egg[i][0]<=0?1:0;
			
			ans=Math.max(ans, rec(egg,curEgg+1,breaked+tmpBreaked));
			
			egg[curEgg][0]+=egg[i][1];
			egg[i][0]+=egg[curEgg][1];
		}
		return ans;
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

17086번: 아기 상어 2

첫째 줄에 공간의 크기 N과 M(2 ≤ N, M ≤ 50)이 주어진다. 둘째 줄부터 N개의 줄에 공간의 상태가 주어지며, 0은 빈 칸, 1은 아기 상어가 있는 칸이다. 빈 칸의 개수가 한 개 이상인 입력만 주어진다.

www.acmicpc.net

 

0. 상어와 가장 먼 칸에서의 상어와의 거리를 구하는 문제

 

1. 이동 방향이 8방향이므로, dir 배열을 8방향으로 구성한다

 

2. 상어를 기준점으로 주변 칸을 bfs로 탐색한다

  • 위치와 거리 정보를 저장하는 class를 만들어 사용한다
  • 탐색하며 거리 정보를 칸에 저장한다
  • 탐색 중 특정 지점에 현재 거리보다 작거나 같은 값이 저장되있다면, 다른 상어가 더 가깝게 있다는 뜻이므로 탐색을 정지한다

 

3. 모든 상어로부터 bfs가 종료되면, 가장 거리가 먼 칸을 탐색, 출력한다

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Main {
	
	static int[][] dir = new int[][] {
		{1,0},{1,1},{0,1},{-1,1},
		{-1,0},{-1,-1},{0,-1},{1,-1}
	};
	static int[][] distanceMap;
	static int[][] map;
	
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		map = new int[n][m];
		distanceMap = new int[n][m];
		
		for(int i = 0; i < map.length; i++) {
			st = new StringTokenizer(br.readLine());
			for(int j = 0; j < map[0].length; j++) {
				map[i][j] = pint(st.nextToken());
				distanceMap[i][j] = Integer.MAX_VALUE;
			}
		}

		int ans = 0;
		for(int i = 0; i < map.length; i++) {
			for(int j = 0; j < map[0].length; j++) {
				if(map[i][j]==1) {
					dfs(i,j);
				}
			}
		}

		for(int i=0; i<map.length; i++) {
			for(int j=0; j<map[0].length; j++) {
				if(ans<distanceMap[i][j])ans=distanceMap[i][j];
			}
		}
		System.out.println(ans);
	}
	
	static void dfs(int x, int y) {
		Queue<point>qu = new LinkedList<>(); 
		qu.offer(new point(x,y,0));
		distanceMap[x][y] = 0;
		
		while(!qu.isEmpty()) {
			point cur = qu.poll();
			
			for(int d=0;d<dir.length;d++) {
				int nx = cur.x + dir[d][0];
				int ny = cur.y + dir[d][1];
				int depth = cur.depth + 1;
				
				if(nx<0 || nx >= map.length || ny<0 || ny>=map[0].length || distanceMap[nx][ny]<=depth) {
					continue;
				}
				
				distanceMap[nx][ny] = depth;
				qu.offer(new point(nx,ny,depth));
			}
		}
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
	

}

class point{
	int x;
	int y;
	int depth;
	public point(int x, int y, int depth) {
		super();
		this.x = x;
		this.y = y;
		this.depth = depth;
	}
}

결과 화면

 

[문제링크]

 

2293번: 동전 1

첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다.

www.acmicpc.net

 

0. 동전으로 특정 액수를 만들어야하는 DP 문제

 

1. n-1번 동전까지 고려한 가짓수 정보가 있다면, n번 동전의 가짓수를 구할 수 있다

  • 냅색 문제와 비슷하다

 

2. n-1번 동전까지의 정보가 있다면, X원짜리 n번 동전으로 k원을 만드는 가짓수는

  • n번 동전 1개 선택 = n-1번 동전까지로 k-X를 만드는 가짓수
  • n번 동전 2개 선택 = n-1번 동전까지로 k-2*X를 만드는 가짓수
  • n번 동전 3개 선택 = n-1번 동전까지로 k-3*X를 만드는 가짓수
  • ...

 

3. 첫번째 동전에서부터 1~k원을 만드는 가짓수를 각각 만들어나간다

  • dp 테이블에 누적시켜 계산한다
  • 예시) 1, 2원짜리로 10원을 만들려고 하면
    • 1원으로 가능한 모든 액수 가짓수는 한가지뿐이다
    • 2원까지 고려하면,
    • dp[2] = dp[2] + dp[2-2] = 1 + 1 =2
    • dp[4] = dp[4] + dp[4-2] = 1 + 2 =3
    • dp[6] = dp[6] + dp[6-2] = 1 + 3 =4
    • dp[8] = dp[8] + dp[8-2] = 1 + 4 =5
    • dp[10] = dp[10] + dp[10-2] = 1 + 5 =6

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int k = pint(st.nextToken());
		int[] coin = new int[n];
		int[] dp = new int [k+1];
		dp[0]=1;
		
		for (int i = 0; i < n; i++) {
			coin[i] = pint(br.readLine());
		}
		
		for (int i = 0; i < n; i++) {
			for (int j = coin[i]; j < k+1; j++) {
				dp[j] += dp[j-coin[i]];
			}
		}
		System.out.println(dp[k]);
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과 화면

[문제링크]

 

11047번: 동전 0

첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000) 둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)

www.acmicpc.net

 

0. 최소한의 갯수로 목표 금액을 맞추는 문제

 

1. 모든 고액권은 소액권의 n배수로 떨어지므로, 항상 가장 큰 액수부터 선택하는게 유리하다

  • 그리디 알고리즘

 

2. 목표 금액을 초과하지 않는 선에서, 가능한 많은 금액을 고액권부터 채워나간다

 

3. 목표 금액이 완성되면, 최종 갯수를 출력

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int k = pint(st.nextToken());
		
		int[]money = new int[n];
		for (int i = 0; i < n; i++) {
			money[i]=pint(br.readLine());
		}
		int cnt=0, idx=n-1;
		while(k!=0) {
			cnt+=k/money[idx];
			k%=money[idx--];
		}
		System.out.println(cnt);
		
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과화면

[문제링크]

 

1743번: 음식물 피하기

첫째 줄에 통로의 세로 길이 N(1 ≤ N ≤ 100)과 가로 길이 M(1 ≤ M ≤ 100) 그리고 음식물 쓰레기의 개수 K(1 ≤ K ≤ N×M)이 주어진다.  그리고 다음 K개의 줄에 음식물이 떨어진 좌표 (r, c)가 주어진다

www.acmicpc.net

 

0. 가장 큰 음식물 덩어리의 크기 구하기

  • 상하좌우로 연결되 있을 경우 한 덩어리로 본다

 

1. 음식물의 여부를 boolean 배열로 표현한다

 

2. 탐색 중 음식물 발견시, dfs 탐색으로 진입한다

  • 이미 탐색한 음식물 제거 (현재 위치 false로 변경)
  • 상하좌우 4방향 각각으로 음식물이 있으면 진행한다
  • 최종적으로 연결된 모든 음식물을 지우고, 그 크기를 반환

 

3. 모든 음식물 덩어리중 가장 큰 값 유지, 출력

 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

public class Main{
	public static void main(String[] args)throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine(), " ");
		int n = pint(st.nextToken());
		int m = pint(st.nextToken());
		int k = pint(st.nextToken());
		boolean[][]map = new boolean[n][m];
		for (int i = 0; i < k; i++) {
			st = new StringTokenizer(br.readLine());
			map[pint(st.nextToken())-1][pint(st.nextToken())-1]=true;
		}
		int ans=0;
		for(int i=0; i<n; i++) {
			for(int j=0; j<m; j++) {
				if(map[i][j])ans=Math.max(ans, dfs(map,i,j));
			}
		}
		System.out.println(ans);
	}
	
	static int dfs(boolean[][]map, int i, int j) {
		int area=1;
		map[i][j]=false;
		if(i+1<map.length && map[i+1][j])area+=dfs(map,i+1,j);
		if(j+1<map[0].length && map[i][j+1])area+=dfs(map,i,j+1);
		if(i-1>=0 && map[i-1][j])area+=dfs(map,i-1,j);
		if(j-1>=0 && map[i][j-1])area+=dfs(map,i,j-1);
		return area;
	}
	
	static int pint(String s) {
		return Integer.parseInt(s);
	}
}

결과화면

1. 달무리 (8*8)

 

달무리

 

ranolp.github.io

 

2. Lanapixel (9*9)

 

LanaPixel - Localization-friendly pixel font

Pixel font with support for many languages.

opengameart.org

 

3. 갈무리체 (9*9)

 

Galmuri

경고 ‒ 건강과 안전을 위하여 사용하기 전에 사용설명서의 「안전을 위한 주의사항」을 읽어 주십시오. 여기에는 당신의 건강과 안전을 위한 중요한 내용이 적혀 있습니다. 이 내용은 홈페이

tbh.kr

 

4. 얌체 (7*7)

 

Romhacking.net - Fonts - Korean Yamche Font

Classic video game modifications, fan translations, homebrew, utilities, and learning resources.

www.romhacking.net

 

5. 지존체 (8*8)

 

Romhacking.net - Fonts - Korean Zizonche

Classic video game modifications, fan translations, homebrew, utilities, and learning resources.

www.romhacking.net

 

0. 시작 이유

 

전원이랑도 연결해야하고! 랜케이블이랑도 연결해야하고! 모니터! 키보드! 마우스!! 내가 전선에 파묻혀 죽겠다!!

해서 기존 모니터/키보드/마우스를 공유해 사용하려고 시도해 보았습니다

 

  • VNC로 윈도우 PC에서 원격 사용하기
  • KVM 스위치 구매해서 윈도우PC와 같이 물려놓고 스위칭

이렇게 2가지 방법을 생각해봤는데.. 돈 안드는 1번에서 잘 해결 되었습니다

 

+ 전 편의상 모니터/키마 다 연결한채로 시작했습니다. GUI 최고!

터미널로도 같은 동작 가능합니다

 

 

1. vim 설치하기

 

기본적으론 vi만 깔려있고 vim이 없습니다

vi보단 vim이 여러모로 편하므로 깔아주면 좋습니다

sudo apt-get install vim

위 명령어를 통해 vim을 설치, 사용 가능합니다

 

 

2. 라즈베리파이 고정 IP 설정하기

 

네트워크 우클릭하면 나오는 Wireless & Wired Network Settings에 들어갑니다

유선랜은 eth0, 무선은 wlan0이 있습니다

IPv4 Address에 사용하고 싶은 IP주소를,

Router에는 공유기 주소를, (보통 저 주소입니다)

DNS 주소는 원하는 DNS 서버의 주소를 입력합니다 (8.8.8.8은 구글 DNS 주소입니다)

재부팅 후 ifconfig 명령어를 터미널에 입력해보면 다음과 같이 설정된 ip를 확인 가능합니다

만약 변경 후 인터넷 접속이 되지 않는다면, 해당 IP를 이미 선점중인 기기가 있는지 확인해야 합니다

  • 공유기 관리자 화면에서 확인하거나
  • 라즈베리파이 종료 후 해당 IP로 핑을 쳤는데 응답이 돌아온다거나
  • 해당 IP로 접속했는데 관리자 화면(프린터 등)이 뜬다거나...

해당 경우에는 다른 빈 IP로 바꿔주면 됩니다

 

 

3. VNC 설정하기

 

우선 윈도우에 VNC viewer 프로그램을 설치해줘야합니다

 

Download VNC Viewer | VNC® Connect

VNC® Connect consists of VNC® Viewer and VNC® Server Download VNC® Viewer to the device you want to control from, below. Make sure you've installed VNC® Server on the computer you want to control. Frequently asked questions How do I install VNC® View

www.realvnc.com

여기서 윈도우용 뷰어를 설치했습니다

 

그리고 라즈베리파이에서 VNC 설정을 켜줘야합니다

여기서 켜줄수도 있고,

터미널 창에 sudo raspi-config 명령 입력 후

Interface Options - VNC Options - Enable 및

Display Options - VNC Resolution 에서 해상도 선택하면 됩니다

 

두 방법의 차이는 찾아봐도 모르겠네요... 둘 다 해도 잘 됩니다

 

이후 설치했던 VNC viewer에서 File - New connection 후 VNC Server에 라즈베리파이의 IP를 입력, (Name은 마음대로)

생성된 아이콘을 클릭해서 Username, Password 입력하면

이렇게 잘 접속이 됩니다

 

 

4. 보안설정

 

 

18. 라즈베리 파이 보안 설정

라즈베리 파이에 있어서 보안은 중요합니다. 보안에 신경 쓰지 않는 것은, 해커가 당신의 허가 없이 라즈베리 파이를 사용하도록 열어두는 것과 같습니다. 어느 수준의 보안이 ...

wikidocs.net

보안은 위 문서 따라가면서 하면 될 것 같습니다

바로 아래 써있지만 잘 되던 윈도우 PC 접근도 차단하는거 보면 잘 작동하는듯 합니다

 

위 과정 중 신규 유저 생성 후 기본 유저(pi) 삭제가 있는데, SSH의 경우는 신규 유저로 접속 후 삭제하면 되고 GUI로 진행할 경우 

위 사진처럼 로그아웃 - Logout 한 후 다른 계정으로 접속하면 해결됩니다

 

만약 xxx번 프로세스가 실행중이라 pi 계정을 삭제할 수 없다고 하면, 다음 명령어를 입력하면 해결됩니다

// xxx = process number
kill -9 xxx

 

 

5. VNC 포트 방화벽 해제하기

 

위 과정에서 UFW 방화벽을 적용하고나니, 윈도우 PC에서 VNC가 작동하지 않습니다

 

Timed out waiting for a response from the computer

그런데 라즈베리파이는 정상적으로 작동 중이고, putty를 통한 SSH 접속은 잘 됩니다

 

원인을 찾아보니 VNC를 사용하기 위한 포트가 방화벽에 차단된 게 문제였습니다 (참고)

 

sudo ufw allow 5900

위 명령어를 통해 5900 포트를 방화벽 규칙에 등록하면, VNC가 다시 잘 작동됩니다

인터넷 연결도 다시 잘 됩니다

 

부팅 중의 과정 등에선 접속되지 않아 조금 아쉽긴 하지만, 이미 세팅된 키보드/마우스/모니터를 이용해서 라즈베리파이까지 이용할 수 있게 되었습니다!

3.3 -> 5 -> 3.3 순으로 찍었습니다

확실히 소음은 3.3이 훨씬 덜하네요

온도는 뭐 빡센작업 시킬거 아니라..시스템 업데이트중에도 53도정도 유지했습니다 (현재 한겨울인점은 감안)

+ Recent posts