기술 블로그

16726번 영과일 학회방 본문

알고리즘 문제/BOJ

16726번 영과일 학회방

parkit 2019. 1. 4. 12:49
728x90
반응형

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



백트래킹 문제인줄 알아서, 백트래킹으로 풀고 제출하였는데


시간 초과가 났다. 그래서 생각해보니 배열 크기가 50*50이므로, 


하나 하나 모든 경우의 수(1*2 크기를 가로로 놓는 경우, 세로로 놓는 경우 등)를 살펴보기에는 너무 오래 걸린다.



그래서, 이분 매칭을 공부한 다음에 다시 풀고 제출하였더니 맞았다. 


더 공부해야겠다.



참고로, 시간 초과가 뜬 코드도 확실한 정답 코드가 아니다.


시간 초과가 뜨고, 정답도 아닌(테스트 케이스가 조차 틀린) 코드도 올려본다. 


물론 틀린 테스트 케이스는 아직 안 찾아봤다.


추가적으로,


정답 코드에서 상하좌우 모두 매칭을 신경써줘야 한다. 


따라서, point vector에 모두 넣는다.





<시간 초과 코드, 백트래킹> - 테스트 케이스 조차 틀린 코드일 확률 99.9999%

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
#include <iostream>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
 
using namespace std;
 
int N = 0, M = 0, total = 0, two = 0, one = 0, var = 0, result = 0;
 
int dy[2= { 01 };
int dx[2= { 10 };
 
int xcnt = 0;
 
char Map[51][51];
 
bool visit[51][51= { false, };
 
bool One[51][51= { false, };
 
int one_calc()
{
    int ret = 0;
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            if (visit[i][j] || Map[i][j] == 'X'continue;
 
            ++ret;
        }
    }
 
    return ret;
}
 
void BackTracking(int pos)
{
    if (pos == (N*- xcnt) / 2)
    {
        result = min(result, two + one_calc());
 
        return;
    }
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            for (int k = 0; k < 2; k++)
            {
                int y = i + dy[k];
                int x = j + dx[k];
 
                if (x < 0 || x >= M || y < 0 || y >= N || visit[y][x] || visit[i][j] || Map[i][j] == 'X' || Map[y][x] == 'X'continue;
 
                visit[i][j] = true;
                visit[y][x] = true;
                two += 1;
 
                BackTracking(pos + 1);
 
                two -= 1;
                visit[i][j] = false;
                visit[y][x] = false;
            }
        }
    }
}
 
int main(void)
{
    scanf("%d %d"&N, &M);
 
    result = 987654321;
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            cin >> Map[i][j];
 
            if (Map[i][j] == 'X'++xcnt;
        }
    }
 
    BackTracking(0);
 
    printf("%d\n", result);
 
    return 0;
}
cs








<정답 코드, 이분 매칭>

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
#include <iostream>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <math.h>
#include <algorithm>
#include <map>
 
using namespace std;
 
#define MAX 51
 
int R = 0, C = 0;
 
int dy[4= { 010-1 };
int dx[4= { 10-10 };
 
int number[MAX][MAX] = { 0, };
 
char Map[MAX][MAX];
 
vector<int> point, Left, Right;
 
vector<vector<int> > v;
 
vector<bool> visit;
 
bool DFS(int start)
{
    if (visit[start]) return false;
 
    visit[start] = true;
 
    for (auto next : v[start])
    {
        if (Right[next] == -1 || DFS(Right[next]))
        {
            Left[start] = next;
            Right[next] = start;
 
            return true;
        }
    }
 
    return false;
}
 
int bm()
{    
    Left = vector<int>(R*+ 1-1);
    Right = vector<int>(R*+ 1-1);
 
    int ret = 0;
 
    for (int i = 0; i < point.size(); i++)
    {
        visit = vector<bool>(R*+ 1false);;
 
        if (DFS(i)) ++ret;
    }
 
    return ret / 2;
    // 2개씩 짝이므로, 나누기 2를 해준다.
}
 
int main(void)
{
    int xcnt = 0;
 
    scanf("%d %d"&R, &C);
 
    v = vector<vector<int> >(R*+ 1);
 
    int cnt = 0;
 
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            cin >> Map[i][j];
 
            if (Map[i][j] == 'X'++xcnt;
 
            point.push_back(cnt);
            
            number[i][j] = cnt++;
        }
    }
 
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            if (Map[i][j] == 'X'continue;
 
            for (int k = 0; k < 4; k++)
            {
                int y = i + dy[k];
                int x = j + dx[k];
 
                if (y < 0 || y >= R || x < 0 || x >= C || Map[y][x] == 'X'continue;
 
                v[number[i][j]].push_back(number[y][x]);    
            }
        }
    }
 
    int two = bm();
 
    int one = R*- 2*two - xcnt;
 
    printf("%d\n", two + one);
 
    return 0;
}
cs




728x90
반응형

'알고리즘 문제 > BOJ' 카테고리의 다른 글

11653번 소인수분해  (0) 2019.01.04
1718번 암호  (0) 2019.01.04
1014번 컨닝  (0) 2019.01.03
1574번 룩 어택  (0) 2019.01.03
4991번 로봇 청소기  (0) 2019.01.03