https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5V4A46AdIDFAWu&categoryId=AV5V4A46AdIDFAWu&categoryType=CODE

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

먼저 두 일꾼이 선택하는 벌통이 겹치지 않도록 모든 경우를 구해준다.

두 일꾼이 벌통을 가로로 m개씩 벌통을 선택했다면 각각의 벌통에서 c를 넘지 않도록 벌꿀을 채취해서 얻는 수익의 최댓값을 구해주면 된다. 문제에 나와있듯이 수익은 벌꿀의 양을 제곱해서 더해준 값이다.

 

 

자세한 설명은 코드 참고! result 변수 대신에 수익을 나타내는 단어로 사용했으면 더 좋았을 것 같다...

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
#include <iostream>
#include <vector>
using namespace std;
 
int ans;
int n, m, c;
int honey[10][10];
bool check[10][10];
vector<int> workers[2];
 
 
//선택한 벌통에서 벌꿀을 채취한다. (sum은 벌통에 들은 꿀의 양, result는 꿀의 양을 제곱해서 얻는 수익)
int selectHoney(int worker,int index, int sum, int result) {
    //채취할 수 있는 최대 양 c를 넘어간 경우 불가능하므로 -1을 리턴
    if (sum > c) return -1;
 
    //m개의 벌통에 대해서 꿀을 채취할지 말지 모두 정해졌다.
    if (index == m) {
        return result;
    }
 
    //제곱한 결과
    int newresult = workers[worker][index] * workers[worker][index];
 
    int rt = 0;
 
    //index번째 벌통에서 꿀을 채취하는 경우
    int tmp1 = selectHoney(worker, index + 1, sum + workers[worker][index], result+newresult);
 
    //index번째 벌통에서 꿀을 채취하지 않는 경우
    int tmp2 = selectHoney(worker, index + 1, sum, result);
    
    //위 의 두가지 경우가 -1이 아니라면 더 작은 값을 리턴해준다.
    if (tmp1 != -1) rt = tmp1;
    if (tmp2 != -1 && rt < tmp2) rt = tmp2;
 
    return rt;
}
 
 
//두명의 일꾼이 벌통을 가로로 m개만큼 선택한다.
void solve(int index, int x) {
    //일꾼 두명 모두 선택이 끝났다.
    if (index > 1) {
        //두 일꾼의 벌통에서 꿀을 채취한다.
        int tmp = selectHoney(0000+ selectHoney(1000);
        if(ans < tmp) ans = tmp;
        return;
    }
 
    for (int i = x; i < n; i++) {
        for (int j = 0; j <= n-m; j++) {
            
            //현재 칸으로부터 m개의 벌통을 선택할 수 있는지 검사
            bool flag = true;
            for (int k = j; k < j + m; k++) {
                if (check[i][k]) {
                    flag = false;
                    break;
                }
            }
            //선택할 수 없다면 다음 칸으로 넘어간다.
            if (!flag) continue;
 
 
            //m개의 칸에 선택 표시를 하고 index번째 일꾼의 벌통에 넣는다.
            for (int k = j; k < j + m; k++) {
                check[i][k] = true;
                workers[index].push_back(honey[i][k]);
                
            }
 
            //다음일꾼의 경우를 탐색
            solve(index+1, i);
 
 
            //위의 탐색에서 돌아왔다면 다음 경우를 위해서 표시를 false로 바꿔주고 벡터에서도 빼준다.
            for (int k = j; k < j + m; k++) {
                check[i][k] = false;
                workers[index].pop_back();
            }
 
        }
    }
}
 
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
 
    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
        ans = 0;
        cin >> n >> m >> c;
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> honey[i][j];
                check[i][j] = false;
            }
        }
 
        solve(0,0);
 
        cout << '#' << tc << ' ' << ans << '\n';
    }
 
    return 0;
}
Colored by Color Scripter
 

https://www.swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5PpFQaAQMDFAUq&categoryId=AV5PpFQaAQMDFAUq&categoryType=CODE

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

1월부터 12월까지 모든 달에 대해서 1일권을 사용할지/1달권을 사용할지/3달권을 사용할지/ 1년권을 사용할지를

모두 해보면 되는데 1년권을 사용할 경우에는 한번에 12개월치를 다 정해주는거나 마찬가지이므로 정답에 미리 넣어놓고 다른 경우들과 비교해주면된다.

 

1일권을 이용하는 경우에는

해당 달의 이용일수X1월권 비용을 전체 비용에 더해준다.

 

1달권을 이용하는 경우에는 

해당 달에 몇번을 이용하든 상관없으므로 1달권의 비용만 더해주면 된다.

 

3달권을 이용하는 경우에는

마찬가지로 3달권의 비용만 더해주면 되는데 대신에 다음 두달치까지 계산되므로 (현재달 + 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <iostream>
using namespace std;
 
int price[4];
int plan[13];
int ans;
 
void solve(int month, int sum) {
    if (month > 12) {
        if (ans > sum) ans = sum;
        return;
    }
 
 
    //이번 달에 수영장을 이용하지 않는 경우
    if (plan[month] == 0) {
        solve(month + 1, sum);
    }
    else {
 
        //1일 이용권을 사용하는 경우
        solve(month + 1, plan[month] * price[0+ sum);
        
        //1달 이용권을 사용하는 경우
        solve(month + 1, price[1+ sum);
 
        //3달 이용권을 사용하는 경우
        solve(month + 3, price[2+ sum);
 
    }
 
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
 
    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
 
        for (int i = 0; i < 4; i++) {
            cin >> price[i];
        }
 
        for (int j = 1; j <= 12; j++) {
            cin >> plan[j];
        }
 
        ans = price[3];
        solve(10);
 
        cout << '#' << tc << ' ' << ans << '\n';
    }
 
    return 0;
}
Colored by Color Scripter
 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWIeV9sKkcoDFAVH

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

자석들이 회전할 방향을 미리 저장해놓고 풀면 쉽게 풀 수 있는 문제이다.

회전시킬 자석의 왼편과 오른편 자석들을 모두 회전할지 안 할지 검사한다.

회전을 하게 된다면 옆에 있는 자석의 반대방향으로 회전한다.

 

오른편의 자석들을 검사할 때는 순차적으로 왼쪽 자석의 2번 날과 오른쪽 자석의 6번 날을 비교하여

다를 경우에 오른쪽 자석의 회전 방향을 왼쪽 자석의 회전방향의 반대방향으로 저장한다.

마찬가지로 왼편 자석들을 검사할떄도 왼쪽 자석의 2번 날과 오른쪽 자석의 6번 날을 비교하여

회전 방향을 저장한다. 

날의 자성이 같아서 회전하지 않을 경우에는 그 앞의 자석들도 회전하지 않으므로 검사를 중단한다.

 

회전 방향을 모두 저장해줬다면 이제 모든 자석들을 회전시킨다.

1이면 시계방향 -1이면 반시계방향으로 회전시켜준다.

0인 경우(회전하지 않는 경우)도 있으므로 조건 처리를 정확히 해주어야 한다.

 

회전까지 모두 마쳤다면 점수를 계산해준다.

문제에서의 화살표 방향은 각 자석의 0번째 날이므로 자석들의 0번째 날이 S극인지(1 인지) 확인하여 계산해주면 된다.

점수는 각각 1, 2, 4, 8로 2의 제곱수로 더해지므로 << 연산으로 쉽게 더해줄 수 있다.

( 1<< 0 은 1이므로 1점 /  1<<1 은 10(2진수)으로 2점 / 1<<2는 100(2진수)으로 4점 / 1<< 3 은 1000(2진수)으로 8점)

 

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
#include <iostream>
using namespace std;
 
int magnet[4][8];
 
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
 
        int k;
        cin >> k;
 
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 8; j++) {
                cin >> magnet[i][j];
            }
        }
 
        while (k-- > 0) {
            int num;
            int dir;
            cin >> num >> dir;
            num -= 1;
 
 
            int dirArr[4= {0,};
            dirArr[num] = dir;
 
 
            //오른쪽 자석 검사
            for (int i = num; i < 3; i++) {
                if (magnet[i][2!= magnet[i+ 1][6]) {
                    dirArr[i + 1= dirArr[i] * -1;
                }
                else {
                    break;
                }
            }
 
 
            //왼쪽 자석 검사
            for (int i = num; i > 0; i--) {
                if (magnet[i][6!= magnet[i - 1][2]) {
                    dirArr[i - 1= dirArr[i] * -1;
                }
                else {
                    break;
                }
            }
 
 
            //회전
            for (int i = 0; i < 4; i++) {
 
                //시계방향 회전
                if (dirArr[i] == 1) {
                    int tmp = magnet[i][7];
                    for (int j = 7; j > 0; j--) {
                        magnet[i][j] = magnet[i][j - 1];
                    }
                    magnet[i][0= tmp;
                }//반시계방향 회전
                else if (dirArr[i] == -1) {
                    int tmp = magnet[i][0];
                    for (int j = 0; j < 7; j++) {
                        magnet[i][j] = magnet[i][j + 1];
                    }
                    magnet[i][7= tmp;
                }
            }
 
        }
 
 
        //점수 계산
        int ans = 0;
        for (int i = 0; i < 4; i++) {
            if (magnet[i][0== 1) {
                ans += (1 << i);
            }
        }
 
        cout << '#' << tc << ' ' << ans << '\n';
 
    }
 
    return 0;
}
Colored by Color Scripter
 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5VwAr6APYDFAWu

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

출발할 수 있는 모든 칸에서부터 출발하여  대각선 방향으로 움직이고 사각형 모양을 그리며 출발한 카페로 돌아온다.

n-1행, n-2행, 0열, n-1열인 곳에서는 사각형을 만들 수 없으므로 출발할 수 없다.

 

각 칸에서 출발하면 오른쪽아래(1,1), 왼쪽 아래(1,-1), 왼쪽 위(-1,-1), 오른쪽 위(-1,1)의 순서로 사각형을 그리도록 했다.

시작점인 경우에만 현재 방향을 유지해서 진행하고 그렇지 않은 경우에는

방향을 꺾어서 이동하는 경우와 현재 방향을 유지한채로 이동하는 경우를 모두 탐색했다.

 

같은 종류의 디저트를 먹으면 안되므로 디저트의 종류를 인덱스로 방문 체크를 해준다.

이동할 곳의 디저트를 아직 먹지 방문하지 않았다면 방문 체크를 해주고 다음 칸으로 이동한다.

이동할 때마다 디저트의 개수를 세주기 위해서  cnt 값을 +1 해서 넘겨준다.

 

이동하다가 이미 방문한 디저트 카페 이지만 그곳이 시작점인 경우에는 출발한 카페로 돌아온 경우이므로

그때까지의 방문한 디저트의 수를 비교해준다.

 
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
#include <iostream>
#include <cstring>
using namespace std;
 
int n, ans;
int sx, sy;
int map[20][20];
int dx[] = {1,1,-1,-1};
int dy[] = { 1,-1,-1,1 };
bool check[101];
 
void solve(int x, int y, int dir, int cnt) {
    
 
    //시작점인 경우
    if (x == sx && y == sy) {
    
            int nx = x + dx[dir];
            int ny = y + dy[dir];
            if (check[map[nx][ny]] == false) {
                check[map[nx][ny]] = true;
                solve(nx, ny, dir,cnt+1);
                check[map[nx][ny]] = false;
            }    
        
    }
    else {
 
        
        //현재 방향 유지하는 경우
        int nx = x + dx[dir];
        int ny = y + dy[dir];
        if (nx >= 0 && ny >= 0 && nx < n && ny < n) {
            if (check[map[nx][ny]] == false) {
                check[map[nx][ny]] = true;
                solve(nx, ny, dir, cnt+1);
                check[map[nx][ny]] = false;
            }
            else if (nx == sx && ny == sy) {
                //방문 표시가 되어있지만 출발점인 경우
                if (ans < cnt) {
                    ans = cnt;
                }
            }
        }
 
 
 
        //방향을 꺾는 경우
        dir += 1;
        if(dir > 3return;
        nx = x + dx[dir];
        ny = y + dy[dir];
        if (nx >= 0 && ny >= 0 && nx < n && ny < n) {
            if (check[map[nx][ny]] == false) {
                check[map[nx][ny]] = true;
                solve(nx, ny, dir, cnt+1);
                check[map[nx][ny]] = false;
            }
            else if (nx == sx && ny == sy) {
                //방문 표시가 되어있지만 출발점인 경우
                if (ans < cnt) {
                    ans = cnt;
                }
            }
        }
    }
    
 
 
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int T;
    cin >> T;
    
    for (int tc = 1; tc <= T; tc++) {
        cin >> n;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> map[i][j];
            }
        }
 
        ans = -1;
        memset(check, falsesizeof(check));
 
        //시작점
        for (int i = 0; i < n - 2; i++) {
            for (int j = 1; j < n - 1; j++) {
                sx = i;
                sy = j;
                check[map[i][j]] = true;
                solve(sx,sy,0,1);
                check[map[i][j]] = false;
                
            }
        }
 
        cout << '#' << tc << ' ' << ans << '\n';
    }
 
    return 0;
}
Colored by Color Scripter
 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AWXRUN9KfZ8DFAUo

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

java로 두 번이나 풀어봤던 문제였는데 16진수로 변환하는 부분이 조금 달라서 푸는데 꽤 어려웠다...

 

 

먼저 한칸씩 회전시켜서 만들 수 있는 모든 숫자를 만들어야 하므로 N/4번만큼 돌려준다.

N/4번만큼 돌리면 처음 상태로 돌아오기 때문이다.

 

 

숫자를 구할 때는 먼저 문자들을 숫자로 변환해준다.

문자 0~9는 '0'을 빼줘서 숫자 0~9로 만들어주고

문자 A~F는 'A'를 빼주고(0이 됨) +10을 해주면 16진수 처럼만들어 줄 수 있다.

(ex. 'A' - 'A' + 10 = 10

      'B' - 'A' + 10 = 11)

 

 

모든 문자를 숫자로 만들어 줬으면 이제 각 변에 저장될 숫자를 만들어 준다.

상자는 네 번 이므로 각 변에는 n/4만큼의 숫자가 들어간다.

n/4개의 숫자를 하나의 숫자(16진수)로  만들어주기 위해서 앞자리 수를 16만큼 계속 곱해준다.

한 변의 숫자가 만들어졌으면 벡터에 추가하고 다음 변의 숫자를 만들어준다.

 

 

만들 수 있는 모든 숫자를 벡터에 넣어줬다면

벡터를 정렬하고 중복을 제거해준다.

k 번째로 큰 수를 구해야 하는데 오름차순으로 정렬되므로 

벡터의 size - k를 해주면 바로 k번째 큰 수를 구할 수 있다.

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 <string>
#include <vector>
#include <algorithm>
using namespace std;
 
int n, k;
string s;
vector<int> num;
 
void getnum() {
    int box[4= {0,};
    int tmp[28];
 
    //각 문자를 숫자로 변환
    for (int i = 0; i < n; i++) {
        if (s[i] >= '0' && s[i] <= '9') {
            tmp[i] = s[i] - '0';
        }
        else { //A~F 는 10~15
            tmp[i] = s[i] - 'A' + 10;
        }
    }
 
 
    //상자의 각 변에 숫자를 넣는다.
    int index = 0;
    //상자의 네 변에 넣어준다.
    for (int i = 0; i < 4; i++) {
        
        //각각의 변에는 n/4개 만큼 들어간다
        for (int j = 0; j < n / 4; j++) {
            //16진수이므로 자릿수가 증가 할때 16을 곱해준다
            box[i] = box[i] * 16 + tmp[index++];
        }
 
        //만들어진 숫자를 벡터에 추가
        num.push_back(box[i]);
    }
 
    
}
 
 
 
void rotate() {
    char tmp = s[n - 1];
    for (int i = n - 1; i > 0; i--) {
        s[i] = s[i - 1];
    }
    s[0= tmp;
}
 
 
 
void solve() {
    
    // n/4 번째에는 0번째와 같아지므로 n/4번 회전
    for (int i = 0; i < n / 4; i++) {
        //만들 수 있는 숫자들을 구한다.
        getnum();
 
        //회전
        rotate();
    }
    
}
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
 
    int T;
    cin >> T;
    for (int tc = 1; tc <= T; tc++) {
        cin >> n >> k;
        cin >> s;
 
 
        solve();
 
 
        //정렬, 중복 제거
        sort(num.begin(), num.end());
        num.erase(unique(num.begin(), num.end()),num.end());
 
 
        //k번째 큰 수를 출력
        int len = num.size();
        cout << '#'<< tc << ' ' << num[len - k] << '\n';
 
 
        //다음 테스트 케이스를 위해서 벡터 초기화
        num.clear();
    }
 
    return 0;
}
Colored by Color Scripter
 

https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AV5V61LqAf8DFAWu

 

SW Expert Academy

SW 프로그래밍 역량 강화에 도움이 되는 다양한 학습 컨텐츠를 확인하세요!

www.swexpertacademy.com

 

이 문제에서 k의 범위는 현재 좌표가 (x, y)라고 했을 때, 

k = |nx-x| + |ny-y|

를 이용해서 k의 범위를 만족하는 (nx, ny)를 구할 수 있다.

 

위의 식을 이용하여 모든 칸에서부터 모든 k의 범위 안에서 집의 수를 구한다.

문제에서 나오는 식을 이용하여 이익을 계산한 후에 손해가 아니라면(이익이 0 이상이라면) 최댓값과 비교한다.

 

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 <cmath>
using namespace std;
 
int n, m;
int maxcnt;
int map[20][20];
 
 
void solve(int x, int y) {
    int profit = 0;
 
    //k의 최댓값 n+2 까지 해본다.
    for (int k = 1; k < n+2; k++) {
 
 
        //k범위에 있는 집들을 모두 세준다.
        int homecnt = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int nx = abs(x - i);
                int ny = abs(y - j);
 
                //k범위 안에 있고 집이 있으면 집의 수 증가
                if (nx + ny < k && map[i][j] == 1) {
                    homecnt++;
                }
            }
        }
 
 
        //이익을 계산
        profit = m*homecnt - (k*+ (k - 1)*(k - 1));
        
        //손해가 아니라면 집의 수를 이전 집의 최대 값과 비교
        if (profit >= 0) {
            if (maxcnt < homecnt) maxcnt = homecnt;
        }
 
    }
}
 
 
 
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
 
    int T;
    cin >> T;
 
    for (int tc = 1; tc <= T; tc++) {
        maxcnt = 0;
        cin >> n >> m;
 
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                cin >> map[i][j];
            }
        }
 
 
        //모든 칸에서 시작
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                solve(i, j);
            }
        }
 
        cout <<'#' << tc << ' ' <<  maxcnt << '\n';
    }
 
    return 0;
}
Colored by Color Scripter
 

+ Recent posts