BOJ : https://www.acmicpc.net/problem/1043

 

게시판을 보니 문제를 이해를 못하시는 분들이 꽤 되시는 것 같아서 문제 설명부터 하겠습니다.

 

간략하게 설명하자면,

진실을 아는 사람을 A, A가 속한 파티에 있는 사람을 B 라고 할 때

A,B 가 속한 모든 파티에서 거짓을 말하면 안됩니다.

 

결국 어떤 파티에서 A가 속하게 되면 => 이 파티 뿐만 아니라 다른 파티에서도 A, B 의 유무를 확인해야 됩니다.

 

예제를 보면

1 2

3

2 3 4

진실을 아는 사람이 만약 0이면 그냥 말그대로 파티 아무데서나 거짓말을 해도 된다가 되지만

만약 여기서 진실을 아는 사람이 2 이면?

파티1은 제외되고 일단 사람2가 파티2, 3에도 존재하는지 확인해봅니다.

파티2에는 사람3밖에 없으므로 거짓을 해도 됩니다. (아직까지는)

파티3에는 사람2가 존재하게 됩니다. => 나머지 사람 3, 4 가 참석할 다른 파티를 확인합니다.

사람3부터 확인하면 사람3은 파티2에 존재합니다. 결국 파티2는 거짓을 하면 안되게 됩니다.

 

이런방향으로 흘러가는 문제입니다.

처음에는 dfs를 통해서 짜보려고 했는데, 구현력이 떨어져서인지 구현이 잘 안되길래 bfs로 변경했습니다.

 

우선적으로 진실을 아는 사람을 모든 파티에 대해 확인할 때,

진실을 아는 사람이 파티에 참가하면 그 파티에 있는 사람까지 큐에 넣었습니다.

 

이 작업이 끝나면 큐에서 하나하나 꺼내면서 모든 파티를 확인해주시면 됩니다.

 

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
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <set>
#include <cmath>
#include <limits>
#include <string>
using namespace std;
 
int person, party, know;
vector<int> know_person;
bool party_person[52][52];
bool visit[52][52];
bool dont_party[52];
 
 
int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
 
    cin >> person >> party >> know;
    for (int i = 0; i < know; i++) {
        int n; cin >> n; know_person.push_back(n);
    }
    for (int i = 0; i < party; i++) {
        int n; cin >> n;
        for (int j = 0; j < n; j++) {
            int m; cin >> m; party_person[i][m] = true;
        }
    }
 
    queue<pair<intint> > q;
    if (know == 0cout << party;
    else {
        for (int i = 0; i < party; i++) {
            for (int j = 0; j < know; j++) {
                if (party_person[i][know_person[j]]) {
                    for (int k = 0; k < 52; k++) {
                        if (party_person[i][k])
                            q.push({ i,k });
                    }
                }
            }
        }
 
        while (!q.empty()) {
            int party_idx = q.front().first;
            int p = q.front().second;
            q.pop();
 
            if (visit[party_idx][p]) continue;
            visit[party_idx][p] = true;
            dont_party[party_idx] = true;
 
            for (int i = 0; i < party; i++) {
                if (party_person[i][p]) {
                    for (int j = 0; j < 52; j++) {
                        if (party_person[i][j]) q.push({ i,j });
                    }
                }
            }
        }
 
        int cnt = 0;
        for (int i = 0; i < party; i++) {
            if (dont_party[i] == false) cnt++;
        }
 
        cout << cnt;
    }
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

'algorithm > BOJ' 카테고리의 다른 글

BOJ 14503번 로봇 청소기  (0) 2020.03.13
BOJ 3709번 레이저빔은 어디로  (0) 2020.03.13
BOJ 1074번 Z  (0) 2020.03.05
BOJ 1026번 보물  (0) 2020.02.28
BOJ 2240번 자두나무  (0) 2020.02.26

BOJ : https://www.acmicpc.net/problem/1074

 

문제를 다시 풀어보았다.

분할정복, 말그대로 분할을 이용한 문제인 것 같다.

 

2*2 형태 부분만 찾으면 되기 때문에

분할은 다음과 같이 했다.

 

왼쪽상단을 fx, fy 라고하고 오른쪽하단을 ly, lx 라고가정

str 은 현재 왼쪽상단에 오게 될 숫자이고 num은 현재 오른쪽하단에 오게 될 숫자이다.

 

이때 4등분을 하게 되면 fx,fy,lx,ly 에 대한 위치를 분할해서 줄 수 잇을 것이며,

str, num 또한 위치에 맞게 분할해줄 수 있다.

2번이나 틀린 문제인데.. long long 을 사용하지 않아서 틀렸다.

2^15 의 좌표만 생각하고 int로만 했다가 WA을 받았다

숫자는 2^15 * 2^15 를 표현해야하니 longlong을 사용하자

 

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
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <algorithm>
#include <set>
#include <cmath>
#include <limits>
using namespace std;
 
int N, r, c;
bool check;
 
void solve(int fy, int fx, int ly, int lx, long long str, long long num) {
    if (check) return;
    
    // 2*2 사이즈이면
    if (ly - fy == 1 && lx - fx == 1) {
        num--;
        if (fy == r && fx == c) cout << num - 3;
        if (fy == r && lx == c) cout << num - 2;
        if (ly == r && fx == c) cout << num - 1;
        if (ly == r && lx == c) cout << num;
        check = true;
        return;
    }
 
    // 범위를 n*n 기준 왼쪽위 1 오른쪽위2 왼쪽아래3 오른쪽아래4 로 가정하면
    // r c 의 위치를 보고 분할한다
 
    int midy = (fy + ly) / 2, midx = (fx + lx) / 2;
    long long div = (num-str) / 4;
    if (r <= midy && c <= midx) solve(fy, fx, midy, midx, str, num - (div * 3));
    if (r <= midy && c > midx) solve(fy, midx+1, midy, lx, str+div, num - (div * 2));
    if (r > midy && c <= midx) solve(midy + 1, fx, ly, midx, str+(div*2), num - div);
    else solve(midy+1, midx+1, ly, lx, str+(div*3), num);
}
 
int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
 
    cin >> N >> r >> c;
    r++, c++;
    int len = pow(2, N);
    solve(11, len, len, 0, len*len);
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter
 

'algorithm > BOJ' 카테고리의 다른 글

BOJ 3709번 레이저빔은 어디로  (0) 2020.03.13
BOJ 1043번 거짓말  (0) 2020.03.13
BOJ 1026번 보물  (0) 2020.02.28
BOJ 2240번 자두나무  (0) 2020.02.26
BOJ 1504번 특정한 최단 경로  (0) 2020.02.24

BOJ : https://www.acmicpc.net/problem/1026

github : https://github.com/junho0956/Algorithm/blob/master/1026/1026/%EC%86%8C%EC%8A%A4.cpp

 

문제의 조건에 A와 B 배열의 값은 음이아닌 정수라고 하였다.

그러므로 두 배열의 각 인자들의 곱에 대한 합이 최소가 되기 위해서는

큰수는 작은수, 작은수는 큰수와 곱해주면 된다.

배열하나는 오름차순, 나머지 하나는 내림차순으로 정렬 후 곱해주면 된다 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <algorithm>
using namespace std;
 
int A[51], B[51];
bool cmp(int& a, int& b) {
    return a > b;
}
int main() {
    int N; cin >> N;
    for (int i = 0; i < N; i++cin >> A[i];
    for (int i = 0; i < N; i++cin >> B[i];
    sort(A, A + N, cmp);
    sort(B, B + N);
    int ans = 0;
    for (int i = 0; i < N; i++) ans += (A[i] * B[i]);
    cout << ans;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

'algorithm > BOJ' 카테고리의 다른 글

BOJ 1043번 거짓말  (0) 2020.03.13
BOJ 1074번 Z  (0) 2020.03.05
BOJ 2240번 자두나무  (0) 2020.02.26
BOJ 1504번 특정한 최단 경로  (0) 2020.02.24
BOJ 1238 파티  (0) 2020.02.23

BOJ : https://www.acmicpc.net/problem/2240

 

처음에는 solve(1번 나무,,) , solve(2번 나무..) 로 둘중에서 큰값을 선택하는 식으로 풀었는데

계속 WA가 뜨길래 어떤 문제점이 있는건지 도통 알수가없어서 포기했다.

몇일뒤에 다시 풀려고 문제를 천천히 읽어봤는데

자두는 1번나무 아래에 위치해 있다는 글을 읽었다..

그래서 solve(1번나무)만 구하니 AC를 받게 되었다.

 

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
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
 
int T, W;
int fall[1001];
int dp[3][1002][32];
 
int solve(int tree, int falling, int moving) {
    if (falling < 0 || moving < 0return 0;
    
    int& res = dp[tree][falling][moving];
    if (res != -1return res;
 
    res = 0;
    if (tree == fall[falling]) res++;
    res += max(solve(tree, falling - 1, moving), solve(tree == 1 ? 2 : 1, falling - 1, moving - 1));
 
    return res;
}
 
int main() {
    ios::sync_with_stdio(0), cin.tie(0);
    
    cin >> T >> W;
    for (int i = 0; i < T; i++) {
        cin >> fall[i];
    }
    memset(dp, -1sizeof(dp));
    cout << solve(1, T, W);
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter

'algorithm > BOJ' 카테고리의 다른 글

BOJ 1074번 Z  (0) 2020.03.05
BOJ 1026번 보물  (0) 2020.02.28
BOJ 1504번 특정한 최단 경로  (0) 2020.02.24
BOJ 1238 파티  (0) 2020.02.23
BOJ 1916번 최소비용 구하기  (0) 2020.02.23

+ Recent posts