반응형

 

티스토리 광고만 붙여놓고 운영을 하지 않았는데 광고가 이렇게 본문 중간에 덕지덕지 붙어있을지는 상상도 못했다..

분명 난 앞에와 뒤에만 설정을 헀는데 본문에도 광고가 계속 들어가 있을줄이야..

광고 설정

 

으 광고 너무 많음

에디터 영역에 광고가 들어가있는 화면

 

 

후.. 에디터에 광고가 덕지덕지 있으면 나 같아도 읽기 싫다. 그래서 어떻게 없앴다 어떻게?

 

HTML 이용해서!

 

티스토리 블로그 관리 > 꾸미기  > 스킨편집 에 들어가서  html 편집 클릭

 

html 편집화면

 

 

CSS 영역에 아래 추가 해주면 된다.

.contents_style은 글이 올라오는 에디터 div의 class 네임이고 .google-auto-placed는 애드센스 광고 영역이라서 에디터 div안에 애드센스 광고만 차단하게 된다.

 

 

.contents_style .google-auto-placed {
   display: none !important;
}



에디터 엔터(내어쓰기) 추가 되는거 막았더니 div Class 이름이 아래처럼 바꼈다.

.tt_article_useless_p_margin contents_style .google-auto-placed {
   display: none !important;
}

 

 

내 CSS 파일

 

 

그러면 귀신같이 광고가 사라져서 가독성이 좋아진다. 끝!

반응형
반응형

백트래킹 ..,,,


N(최대 100) 장중에 3장을 뽑아서 M보다 작은 최대값을 찾아라.!

100C3 이므로 시간초과가 나지 않는다. 메모리 초과도 나지 않는다.

백트래킹으로 100C3의 모든 경우를 계산해주면 된다.


풀이

1. 백트래킹으로 부분집합 (모든 경우의 수) 를 계산한다.

2. 3개만 선택하면 되므로 depth는 2일때이다. (0부터 시작했으니깐)

3. M보다 크지않은 최대값을 고르면 끄읏.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
class Main {
    static BufferedReader br;
    static int N;
    static int M;
    static int max;
    static int result;
    static int[] arr;
    static boolean[] visited;
    static String[] str;
 
    public static void main(String[] args) throws Exception {
        br = new BufferedReader(new InputStreamReader(System.in));
        str = br.readLine().split(" ");
        N = Integer.parseInt(str[0]);
        M = Integer.parseInt(str[1]);
        max = Integer.MAX_VALUE;
        arr = new int[N];
        visited = new boolean[N];
        str = br.readLine().split(" ");
        for (int i = 0; i < N; i++) {
            arr[i] = Integer.parseInt(str[i]);
        }
        //-----------------입력부-----------------
        
        for (int i = 0; i < N; i++) {
            visited[i] = true;
            DFS(i, 0, arr[i]);
            visited[i] = false;
        }
        System.out.println(result);
    }
 
    public static void DFS(int start, int depth, int sum) {
        //depth가 0부터 시작 했으므로 depth==2이면 3개의 카드를 골랐을 경우이다.
        if (depth == 2) {
            //M보다 크지않은 최대값을 고른다.
            if (Math.abs(M - sum) < max && sum <= M) {
                max = Math.abs(M - sum);
                result = sum;
            }
            return;
        }
        //3개를 고르는 알고리즘.visited[] 함수를 통해 백트래킹으로 구현했다.
        for (int i = start; i < N; i++) {
            if (visited[i])
                continue;
            visited[i] = true;
            DFS(i + 1, depth + 1, sum + arr[i]);
            visited[i] = false;
        }
    }
 
}
cs


반응형
반응형

DP ..,,,..

이것도 초등부 문제...?

초등부라....... 하하하하


조건

1. 계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.

2. 연속된 세 개의 계단을 모두 밟아서는 안된다. 단, 시작점은 계단에 포함되지 않는다.

3. 마지막 도착 계단은 반드시 밟아야 한다.


풀이

1. 한칸이나 두칸 이동할 수 있다.

2. 연속된 세개의 계단을 밟으면 안된다는 뜻는 (1칸 이동 -> 1칸 이동) 이 불가하다는 뜻이다.

그렇다면 해결 방법은 (2칸이동 + 1칸이동), (1칸이동 + 2칸이동), (2칸이동 + 2칸이동) 경우의 수가 생긴다.

이때 2칸이동을 했을경우에는 이전에 2칸이동을 했을 경우와 1칸 이동을 했을 경우가 생긴다.

2칸이동을 했을때와 1칸이동을 했을때의 최대값을 비교하여 2칸이동한 위치를 더해줘야한다.

여기서 dp 2차원 배열을 만들어 dp[x][0] 때는 1칸이동, dp[x][1] 일때는 2칸이동을 나타냈다.

3. 마지막 계단을 밟아야 하므로 그 위치에 저장된 값을 출력해준다.

코드를 보자.

소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
class Main {
 
    static BufferedReader br;
 
    public static void main(String[] args) throws Exception {
 
        br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        int[] arr = new int[N+1];
        int[][] dp = new int[N+1][2];
 
        for (int i = 0; i <N; i++) {
            arr[i] = Integer.parseInt(br.readLine());
        }
        //dp[N][0] 은 한번에 한칸 올랐을 때
        //dp[N][1] 은 한번에 두칸 올랐을 때
        dp[0][0= arr[0];
        dp[1][0= dp[0][0]+ arr[1];
        dp[1][1= arr[1];
        
        for(int i=2; i<N; i++){
            //이전에 두칸 올랐을때만 현재 한칸을 이동할 수 있다.
            //이전에 한칸 올랐다면 연속된 세칸을 밟을 경우가 생긴다.
            dp[i][0= dp[i-1][1+ arr[i];
            
            //두칸을 이동할 경우 어떠한 제한조건이 없다. 두칸전 위치의 최대값과 현재값을 더해준다.
            dp[i][1= Math.max(dp[i-2][0], dp[i-2][1])+arr[i];
        }
        System.out.println(Math.max(dp[N-1][0], dp[N-1][1]));
        
        
    }
}
cs


반응형
반응형
BFS ...,,,,, 비트 마스크 .,,.,..


이거 어떻게 풀지 몰라서 다른 사람들 코드를 보고 이해한 후 풀었다.

비트마스크가 이렇게 쓰일 수 있다는 것이 너무 신기했다.


풀이

1.  BFS를 통해 탐색을 하면 된다.

2. 키의 개수가 a~f 까지, 6개이다. N과 M의 최대값은 50, 2^6은 64이므로 최대 50x50x64 이므로 배열을 만들어서 관리해도 크게 상관없다.

3. 해당위치에 어떤 키를 갖고 방문했는지 판단을 하여 재 방문 하지 않게 한다. 이때 비트마스크를 사용한다.

비트마스크를 이용한 키를 이용하는 방법은 2진수를 생각하면 된다.

키는 총 6개 비트는 6개를 사용한다. << , >> 이용한 shift 연산을 하면 해당 비트를 출력또는 변경 시킬 수 있다.

예를들어)

a키를 갖고 있을 경우는 100000 가 되고

a,b키를 갖고 있는 경우에는 110000

a,b,c키를 갖고 있는 경우 111000

모든 키를 갖고 있는경우는 111111이 된다.


이러한 비트마스크를 이용하여 문제를 풀어보자.

(1,1)에 a키를 갖고 방문했을 때는 Boolean check[1][1][0]에 접근하여 true로 값을 바꾼다.

이후 a키만 갖고 있을때는 Check[][][] 함수를 통해 (1,1)은 방문하지 않는다.

하지만 b키 또는 다른 키들을 획득한 후 (1,1)에 방문할 경우 Boolean check[1][1][1~64] 사이의 값을 접근하는 것이므로 (1,1)에 방문 할 수 있다.  

4. 위의 경우를 생각하여 문제를 풀면 된다.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
 
public class Main {
    static int N;
    static int M;
    static char[][] arr;
    static boolean[][][] check;
 
    static int[] dx = { 1-100 };
    static int[] dy = { 001-1 };
 
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
        // BufferedReader br = new BufferedReader(new
        // InputStreamReader(System.in));
 
        int Testcase = Integer.parseInt(br.readLine());
        for (int t = 1; t <= Testcase; t++) {
            String[] str = br.readLine().split(" ");
            N = Integer.parseInt(str[0]);
            M = Integer.parseInt(str[1]);
            Dot start = null;
            arr = new char[N][M];
            check = new boolean[N][M][1 << 6];
 
            for (int i = 0; i < N; i++) {
                str = br.readLine().split("");
                for (int j = 0; j < M; j++) {
                    arr[i][j] = str[j].charAt(0);
                    if (arr[i][j] == '0') {
                        start = new Dot(i, j, 0);
                    }
                }
            }
            System.out.print("#" + t + " ");
            System.out.println(BFS(start));
 
        }
    }
 
    public static int BFS(Dot start) {
        Queue<Dot> q = new LinkedList<Dot>();
        q.add(start);
        check[q.peek().x][q.peek().y][0= true;
        int Hour = 0;
        while (!q.isEmpty()) {
            int size = q.size();
            for (int qsize = 0; qsize < size; qsize++) {
                Dot d = q.poll();
                int currentX = d.x;
                int currentY = d.y;
                int currentKey = d.key;
                System.out.println(currentX + " " + currentY);
                if (arr[currentX][currentY] == '1') {
                    return Hour;
                }
 
                for (int i = 0; i < 4; i++) {
                    int nextX = currentX + dx[i];
                    int nextY = currentY + dy[i];
                    int key = currentKey;
                    
                    //범위 밖이면 통과
                    if (nextX < 0 || nextY < 0 || nextX >= N || nextY >= M) {
                        continue;
                    }
                    // 벽을 만나면 통과
                    if (arr[nextX][nextY] == '#') {
                        continue;
                    }
                    //a 와 f 사이 키 일때 해당 위치의 값을 1로 만들어준다.
                    if ('a' <= arr[nextX][nextY] && arr[nextX][nextY] <= 'f') {
                        key |= (1 << arr[nextX][nextY] - 'a');
                    }
                    //A 와 F 사이 키를 갖고 있는지 확인한 후 없다면 패스한다.
                    if ('A' <= arr[nextX][nextY] && arr[nextX][nextY] <= 'F') {
                        if ((key & (1 << (arr[nextX][nextY] - 'A'))) == 0) {
                            continue;
                        }
                    }
                    //해당 위치에 똑같은 키들을 갖고 방문했다면 패스
                    if (check[nextX][nextY][key]) {
                        continue;
                    }
                    //해당 위치에 똑같은 키들을 갖고 방문한 적 없으면 방문 후, 재 방문 금지하기 위한 조건걸어둠.
                    check[nextX][nextY][key] = true;
                    q.add(new Dot(nextX, nextY, key));
                }
            }
            Hour++;
        }
        return -1;
    }
}
 
class Dot {
    int x;
    int y;
    int key;
 
    Dot(int x, int y, int key) {
        this.x = x;
        this.y = y;
        this.key = key;
    }
}
 
cs


반응형
반응형

DP ....,,,,


재귀로 예전에 맞았었는데 재채점 이후 시간초과가 났다.

그래서 DP로 작성했더니 통.과.!


사용된 0과 1의 갯수를 출력하는 문제였기 때문에 나는 0의 배열과 1의 배열을 만들었다.

의 재귀 함수를 DP로 바꾸면 된다. 


풀이

1. 피보나치 값이 0과 1일때는 바로 "1 0", "0 1" 로 출력한다.

2. arr[][] 함수를 만들어서 0과 1을 따로 카운트 한다.

3. 현재값은 전의값과 전전값이 합쳐진 값이기 때문에 아래와 같은 방정식이 나오게 된다.

arr[N] = arr[N-1] + arr[N-2]

위의 식을 이용하면 끄읏.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
 
class Main {
 
    static BufferedReader br;
 
    public static void main(String[] args) throws Exception {
 
        //br = new BufferedReader(new InputStreamReader(System.in));
        br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
        int TestCase = Integer.parseInt(br.readLine());
 
        for (int t = 0; t < TestCase; t++) {
            int n = Integer.parseInt(br.readLine());
            int[][] arr = new int[n+1][2];
            // 0일때
            if(n==0) {
                System.out.println("1 0");
                continue;
            }
            // 1일때
            if(n==1){
                System.out.println("0 1");
                continue;
            }
            arr[0][0= 1;
            arr[1][1= 1;
            
            for(int i=2; i<=n; i++){
                arr[i][0= arr[i-1][0]+arr[i-2][0];
                arr[i][1= arr[i-1][1]+arr[i-2][1];
                
            }
 
            System.out.println(arr[n][0]+" "+arr[n][1]);
 
        }
    }
}
cs


반응형
반응형

문자열 처리...,,, 출력..,,


풀이

1. StringBuffered 클래스를 사용하면 된다.

2. Split 함수를 사용하면 된다.

3. 그냥 외운다.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.io.BufferedReader;
import java.io.InputStreamReader;
 
class Main {
 
    static BufferedReader br;
 
    public static void main(String[] args) throws Exception {
 
        br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        String[] str = br.readLine().split("");
        int sum = 0;
        for (int i = 0; i < N; i++) {
            sum += Integer.parseInt(str[i]);
        }
        System.out.println(sum);
 
    }
}
cs


반응형
반응형

백트래킹 (순열(?)),,,,...,


2018년 상반기 CE/IM 2번 문제..   DS보단 문제가 쉬웠던 듯 하다..

삼성 SW테스트는 참 백트래킹을 좋아하는 듯하다..


풀이

1. 치킨집과 집을 각각 Person List , Chichken List에 저장해준다. (나는 ArrayList를 사용함)

2. 치킨집들 중에 M개를 선택해야한다.

00000 부터 11111 까지 계산후 1의 갯수가 M개 일때 계산을 할 수 있지만, 그러면 시간초과가 날 듯 싶어 백트래킹을 이용하여 풀었다.

정확히 M개일때 그 이상으로 넘어가지 않도록 return 해주면 시간이 단축된다.

예를 들어) 치킨집 5개중 3개를 선택해야하는 경우 치킨집 1, 2, 3, 4, 5 가 존재한다.

이때, (1 2 3), (1 2 4), (1 2 5), (2 3 4), (2 3 5), (3 4 5)  의 경우의 수가 생긴다.

경우의 수를 만드는 것은 코드를 통해 확인하길...

3. 경우의 수를 만들었다면 미리 저장해놨던 Person을 선택된 Chicken 집에 각각 거리를 비교해서 최단 거리를 찾는다.

4. 경우의 수마다 모든 최단 거리를 찾아 최단 거리들 중 가장 짧은 최단 거리를 비교하여 찾아내면 된다.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
 
class Main {
    static int N;
    static int M;
    static int[][] arr;
    static ArrayList<Dot> chicken;
    static ArrayList<Dot> person;
    static int[] output;
    static boolean[] visited;
    static int result;
 
    public static void main(String[] args) throws Exception {
 
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
 
        String[] str = br.readLine().split(" ");
        N = Integer.parseInt(str[0]);
        M = Integer.parseInt(str[1]);
        arr = new int[N][N];
        result = Integer.MAX_VALUE;
        chicken = new ArrayList<Dot>();
        person = new ArrayList<Dot>();
 
        for (int i = 0; i < N; i++) {
            str = br.readLine().split(" ");
            for (int j = 0; j < N; j++) {
                arr[i][j] = Integer.parseInt(str[j]);
                if (arr[i][j] == 1) {
                    //1일때는 사람 list에 추가
                    person.add(new Dot(i, j));
                } else if (arr[i][j] == 2) {
                    //2일때는 치킨 list에 추가
                    chicken.add(new Dot(i, j));
                }
            }
        }
        //-------입력부-------//
        
        //치킨 집 선택을 위한 배열 visited, output
        visited = new boolean[chicken.size()];
        output = new int[chicken.size()];
        
        //치킨 집 선택
        for (int i = 0; i < chicken.size(); i++) {
            visited[i] = true;
            ChickenSelection(i, 0);
            visited[i] = false;
        }
        System.out.println(result);
    }
    
    //치킨집 선택을 위한 함수
    public static void ChickenSelection(int start, int depth) {
        output[depth] = start + 1;
        
        for (int i = start; i < chicken.size(); i++) {
            if (visited[i])
                continue;
            visited[i] = true;
            ChickenSelection(i, depth + 1);
            visited[i] = false;
        }
        //치킨집이 선택되었을 경우
        //(치킨집이 최대 M개 이므로 depth은 M-1 이 되어야한다. 0부터 시작했으니깐)
        if (depth == M - 1) {
            int sum = 0;
            int currentM = 0;
            //사람이 갈수 있는 치킨집의 경우중 가장 최소값을 선택한다.
            //person 한명씩 모든 Chicken 집을 선택하여 최소값을 비교한다.
            for (int i = 0; i < person.size(); i++) {
                int min = Integer.MAX_VALUE;
                for (int j = 0; j < M; j++) {
                    currentM = Calc(person.get(i), chicken.get(output[j] - 1));
                    min = Math.min(min, currentM);
                }
                //최소값일 경우 더한다.
                sum = sum + min;
            }
            //치킨집 경우의 수마다 다른 최소거리중 가장 작은 최소거리를 선택한다.
            result = Math.min(result, sum);
        }
    }
    
    //위치 거리 계산 함수
    public static int Calc(Dot d1, Dot d2) {
        return Math.abs(d1.x - d2.x) + Math.abs(d1.y - d2.y);
    }
}
 
class Dot {
    int x;
    int y;
 
    Dot(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

cs


반응형
반응형

모든 경우의 수 + dfs ,,,...


2018년 상반기 ds 1번문제이다. 어제 보고 와서 다시한번 복기하는 식으로 문제를 풀었다.

열심히 공부했지만 막상 시험장에 가보니 긴장감과 압박감에 문제를 어떻게 해결해야하는지 생각나는데 1시간정도가 걸린것 같다.

10개의 테스트케이스를 다 맞추긴했지만 내부테스트케이스에서 걸릴지 미지수다... 좀 더 빨리 생각해냈다면 금방 풀었을 것인데..


풀이

1. CCTV 의 개수를 모두 센다. 그 후 cctv를 전부 돌려본다. 

예를 들어) 1은 상, 2는 우, 3는 하, 4는 좌로 설정하고  cctv의 개수를5개로 가정했을 때

(1 1 1 1 1), (1 1 1 1 2), (1 1 1 1 3), ....(2 2 2 2 2), .....(3 3 3 3 3), ........(4 4 4 4 2), (4 4 4 4 3), (4 4 4 4 4) 처럼 모든 경우의 수를 만들어 본다.

2. 만들어진 수를 통해 해당 방향으로 돌려준다. 

여기서 cctv의 숫자에 따라서 감시하는 방향이 달라진다.

예를 들어 1번 cctv의 경우, 1일때 상, 2일때 우, 3일때 하, 4일때 좌를 감시해야한다.

그러나 2번 cctv의 경우, 1일때 상 우, 2일때 우 하, 3일때 하 좌, 4일때 좌 상을 감시해아한다.

이 방향의 조합을 순서에 맞게 짜는 방법을 몰라 하나의 Watch() 함수를 만들어 방향을 설정해주었다.

3. 모든 조합의 방향을 만들어보고 DFS를 통해 감시영역을 한 방향으로 진행시키면 된다. 이때 Move() 함수를 사용했다.

4. 모든 감시방향 설정을 끝낸 후 사각지대의 값을 비교해가며 최소값을 찾아주면 된다. 최소값 비교후 다음 탐색을 위해 2차원 배열을 초기화 시켜줘야한다.

아주 직관적인 문제여서 코드를 보면 쉽게 이해할 수 있을 것이다.



소스

allCase를 통해 경우의 수를 만들었고 경우의 수가 만들어질때마다 Watch -> Move 함수를 통해 해당 cctv의 감시영역을 설정해줌.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
 
class Main {
    static int N;
    static int M;
    static int[][] arr;
    static int[][] temp;
    static ArrayList<Dot> list;
    static int size;
    static int[] output;
    static int count;
    static int result;
 
    public static void main(String[] args) throws Exception {
 
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] str = br.readLine().split(" ");
        N = Integer.parseInt(str[0]);
        M = Integer.parseInt(str[1]);
        arr = new int[N][M];
        temp = new int[N][M];
        list = new ArrayList<Dot>();
        count = 0;
        result = Integer.MAX_VALUE;
        for (int i = 0; i < N; i++) {
            str = br.readLine().split(" ");
            for (int j = 0; j < M; j++) {
                arr[i][j] = Integer.parseInt(str[j]);
                temp[i][j] = arr[i][j];
                if (arr[i][j] != 6 && arr[i][j] != 0) {
                    //cctv 일때 리스트에 저장한다.
                    list.add(new Dot(i, j));
                }
 
            }
        }
        
        //------입력부------//
        size = list.size();    //cctv 갯수
        output = new int[size];    //모든 조합을 만들어줄 배열
        
        //cctv가 존재하지 않을때
        if (size == 0) {
            Check();
            result = count;
        }
        //cctv가 존재할때
        else {
            for (int i = 0; i < 4; i++) {
                //cctv 전부 모든 방향 계산을 해준다.
                output[0= i + 1;
                allCase(i, 0);
            }
        }
        System.out.println(result);
 
    }
    //allCase 함수는 cctv가 감시하는 모든 경우의 수를 만들기 위해 사용한다.
    public static void allCase(int start, int depth) {
        if (depth == size - 1) {
            for (int i = 0; i < size; i++) {
                Dot d = list.get(i);
                // 1부터 N개의 cctv를 모두 돌린다.
                Watch(d, arr[d.x][d.y], output[i]);
 
            }
            Check(); //사각지대가 얼마나 있는지 체크
            result = Math.min(result, count);    //사각지대가 최소일때 저장
            Reset();    //감시하는 장소 초기화
            return;
        }
 
        for (int i = 0; i < 4; i++) {
            //조합을 만들기 위해 사용
            output[depth + 1= i + 1;
            allCase(i, depth + 1);
        }
 
    }
    
    //Wacth 함수는 cctv의 종류와 방향을 따라 감시하는 위치를 정해준다.
    public static void Watch(Dot d, int num, int dir) {
        if (num == 1) {
            if (dir == 1) {
                Move(d, 1);
            } else if (dir == 2) {
                Move(d, 2);
            } else if (dir == 3) {
                Move(d, 3);
            } else if (dir == 4) {
                Move(d, 4);
            }
 
        } else if (num == 2) {
            if (dir == 1) {
                Move(d, 1);
                Move(d, 3);
            } else if (dir == 2) {
                Move(d, 2);
                Move(d, 4);
            } else if (dir == 3) {
                Move(d, 1);
                Move(d, 3);
            } else if (dir == 4) {
                Move(d, 2);
                Move(d, 4);
            }
        } else if (num == 3) {
            if (dir == 1) {
                Move(d, 1);
                Move(d, 2);
            } else if (dir == 2) {
                Move(d, 2);
                Move(d, 3);
            } else if (dir == 3) {
                Move(d, 3);
                Move(d, 4);
            } else if (dir == 4) {
                Move(d, 4);
                Move(d, 1);
            }
        } else if (num == 4) {
            if (dir == 1) {
                Move(d, 1);
                Move(d, 2);
                Move(d, 3);
            } else if (dir == 2) {
                Move(d, 2);
                Move(d, 3);
                Move(d, 4);
            } else if (dir == 3) {
                Move(d, 3);
                Move(d, 4);
                Move(d, 1);
            } else if (dir == 4) {
                Move(d, 4);
                Move(d, 1);
                Move(d, 2);
            }
        } else if (num == 5) {
            Move(d, 1);
            Move(d, 2);
            Move(d, 3);
            Move(d, 4);
        }
 
    }
    
    
    //Move 함수는 DFS를 통해 한 방향을 감시한다.
    //2차원 배열의 값을 바꿔준다.
    public static void Move(Dot d, int dir) {
 
        int currentX = d.x;
        int currentY = d.y;
        int nextX = currentX;
        int nextY = currentY;
 
        if (dir == 1) {
            nextX = currentX - 1;
            nextY = currentY;
        } else if (dir == 2) {
            nextX = currentX;
            nextY = currentY + 1;
        } else if (dir == 3) {
            nextX = currentX + 1;
            nextY = currentY;
        } else if (dir == 4) {
            nextX = currentX;
            nextY = currentY - 1;
        }
        //다음 위치가 범위 밖일 때는 종료
        if (nextX < 0 || nextY < 0 || nextX >= N || nextY >= M) {
            return;
        }
        //다음 위치가 벽이라면 종료
        if (arr[nextX][nextY] == 6) {
            return;
        }
        //다음 위치가 0일때는 1로 바꾸지만 나머지 숫자는 바꾸지 않고 넘어간다.
        //숫자를 바꾸게 되면 다음 list를 사용할때 문제가 생긴다.
        //정확히는 Move 함수의 num값이 바뀌므로 바꾸지 않고 넘어간다.
        if (arr[nextX][nextY] == 0) {
            arr[nextX][nextY] = 1;
        }
        Move(new Dot(nextX, nextY), dir);
 
    }
    
    //사각지대가 얼마나 있는지 체크하는 함수
    public static void Check() {
        count = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (arr[i][j] == 0) {
                    count++;
                }
            }
        }
    }
    //2차원 배열을 초기화 하는 함수
    public static void Reset() {
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                arr[i][j] = temp[i][j];
            }
        }
    }
}
 
class Dot {
    int x;
    int y;
 
    Dot(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
cs


반응형
반응형

다이나믹 프로그래밍...


다이나믹 프로그래밍이라는 단어를 못봤다면 아마도 틀렸을 것이다. 백트래킹으로 문제를 풀었을 듯싶다.

그러면 시간초과나 메모리 초과가 나겠지...


풀이

1. 연속된 몇개의 숫자이다. 그러므로 연속된 값만 생각해주면 된다.

2. 두가지 경우만 생각하면된다.

이전부터 계속 연속한 값 vs 현재부터 연속된 값 의 경우를 따지면 된다.

위의 경우가 두경우를 따졌을 때, 그 위치값에서의 최대값을 나타낸 것이다.

예를 들어 10 + (-4) 의 연속된 경우와 -4부터 시작되는 경우 10 + (-4) 가 크므로 6이 된다.

그 다음 값은 10+ (-4) + 3 vs 3 인데 이때도 10 + (-4) + 3 이 크므로 dp에는 9가 저장된다.

그 다음을 계산해도 1번 + 2번 + 3번 + 4번의 값은 (4번) 보다 크므로 10이 된다.

(2번) + (3번) + (4번) or (3번) +(4번) 은 이미 이전에 계산됬기때문에 상관 안해도 된다.

이대로 가서 최대값을 찾아주면 된다.


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
 
class Main {
    public static void main(String[] args) throws Exception {
        //BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
        int N = Integer.parseInt(br.readLine());
        String[] str = br.readLine().split(" ");
        int[] arr = new int[N];
        int[] dp = new int[N];
        int max;
        for (int i = 0; i < N; i++) {
            arr[i] = Integer.parseInt(str[i]);
        }
        dp[0= arr[0];
        max = arr[0];
        for(int i=1; i<N; i++){
            dp[i] = Math.max(dp[i-1]+arr[i], arr[i]);
            
            max = Math.max(max, dp[i]);
        }
        System.out.println(max);
        
    }
}
cs


반응형
반응형

DP...,, DFS(?)...,,


2017년 상반기 CE/IM 2번 문제

나는 DP로 풀었다. 예전에는 못풀었는데 프로그래밍을 하다보니 실력이 늘긴 했나보다..


풀이

1. T[], P[], dp[] 배열을 사용한다.

T[] 배열은 날짜, P[] 배열은 수입금, dp[]는 당일까지 최대 수입금 을 저장한다.

2. 첫 날부터 마지막날 까지 계산하는데 계산중인 날 기준으로 이전보다 최대수입이 작으면 안된다.

dp[i] = Math.max(dp[i], max);

3. (현재 날짜 + 상담 완료) 날짜의 수입금은

(현재 날짜 + 상담 완료)날짜에 저장된 최대 수입과 와 (오늘 이전까지 최대 수입 + 오늘 버는 수입) 중 최대값을 저장한다. 

dp[T[i]+i] = Math.max(dp[T[i]+i],P[i]+dp[i]);

4. 최대수입을 저장한다.

max = Math.max(max, dp[i]);

아 설명 진짜 못한다. 아무튼 코드를 보다보면 이해 할 수 있을 꺼에요....


소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
 
class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
 
        int N = Integer.parseInt(br.readLine());
 
        //N+10 을 해준 이유는 마지막날 + 5일일 때 배열 에러가 날 수 있으므로 넉넉히 잡아준다. 
        int[] T = new int[N+10];
        int[] P = new int[N+10];
        int[] dp = new int[N+10];
        int max = 0;
        String[] str;
        for (int i = 1; i <=N; i++) {
            str = br.readLine().split(" ");
            T[i] = Integer.parseInt(str[0]);
            P[i] = Integer.parseInt(str[1]);
        }
        //------------입력부------------//
        
        
        for (int i = 1; i <=N+1; i++) {
            //이전까지의 최대 수입을 비교해서 최대 수입을 현재에도 저장해준다.
            //이전에 최대수입이 났을 수 있으므로
            //ex) 3,7,(5 예상) 이라고 하면 5의 값은 7로 바꿔주는게 최대수입을 얻는데 맞다.
            dp[i] = Math.max(dp[i], max);
            //이전에 저장된 최대수익 vs 이번 움직임으로 생긴 최대 수익
            dp[T[i]+i] = Math.max(dp[T[i]+i],P[i]+dp[i]);
            //출력될 최대 수입
            max = Math.max(max, dp[i]);
            
        }
        System.out.println(max);
    }
}
cs


반응형

+ Recent posts