[문제 링크]

 

6603번: 로또

문제 독일 로또는 {1, 2, ..., 49}에서 수 6개를 고른다. 로또 번호를 선택하는데 사용되는 가장 유명한 전략은 49가지 수 중 k(k>6)개의 수를 골라 집합 S를 만든 다음 그 수만 가지고 번호를 선택하는 것이다. 예를 들어, k=8, S={1,2,3,5,8,13,21,34}인 경우 이 집합 S에서 수를 고를 수 있는 경우의 수는 총 28가지이다. ([1,2,3,5,8,13], [1,2,3,5,8,21], [1,2,3,5,8,34], [1,2

www.acmicpc.net


알고리즘은 다음의 순서로 진행된다.

1. 첫번째 수(k)와 k개의 숫자를 입력 받아 배열에 담는다 ( k==0 일 때 종료)

2. 입력받은 배열을 가지고 6개 숫자를 뽑는 조합을 사전 순으로 출력한다.

---> 단, 숫자를 오름차순으로 입력받으므로 별도의 정렬은 하지 않아도 된다.

---> 순서만 다른 숫자조합까지 출력하지 않도록 주의해야한다.


#include <iostream>
#include <vector>
using namespace std;
 
vector<int> numArr;
vector<int> picked;
vector<bool> visited;
void Solution(vector<int>& picked,int toPick)
{
    if (toPick == 6)    // 기저사례. 6개 숫자 뽑았으면 출력
    {
        for (int i = 0; i < 6; i++)
            cout << picked[i] << ' ';
        cout << '\n';
        return;
    }
    int len = numArr.size();
    for (int i = 0; i < len; i++)
    {
        if (!picked.empty())
            if (picked.back() > numArr[i]) continue;    
        if (visited[i] == truecontinue;
        visited[i] = true;
        picked.push_back(numArr[i]);
        Solution(picked, toPick + 1);
        visited[i] = false;
        picked.pop_back();
    }
}
int main(void)
{
    int num;
    while (1)
    {
        cin >> num;
        if (num == 0break;
        for (int i = 0; i < num; i++)
        {
            int n;
            cin >> n;
            numArr.push_back(n);
            visited.push_back(false);
        }
        Solution(picked, 0);
        cout << '\n';
       numArr.clear();
       visited.clear();
    }
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 7day

내일도 열심히! 

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

백준 1966번: 프린터 큐  (0) 2020.04.13
백준 14888번: 연산자 끼워넣기  (0) 2020.04.12
백준 7568번: 덩치  (0) 2020.04.11
백준 14502번: 연구소  (0) 2020.04.11
백준 2231번: 분해합  (0) 2020.04.11

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
 
vector<pair<intint>> man;
vector<int> ranking;
int num;
 
void Solution(int toPick)
{
    if (toPick == num)    // 기저사례. num명의 등수를 다 계산했다면 등수를 출력한다
    {
        for (int i = 0; i < num; i++)
            cout << ranking[i] << ' ';
        return;
    }
 
    int cnt = 1;
    for (int i = 0; i < num; i++)
    {
        if (i == toPick) continue;    // 자기 자신과는 비교하지 않는다
        if (man[toPick].first < man[i].first && man[toPick].second < man[i].second) cnt++;
        // 자신보다 키와 몸무게가 더 큰 사람이 있다면 순위를 증가시킨다
    }
    ranking.push_back(cnt);
    Solution(toPick + 1);    // 등수 매긴 사람 수를 1 증가시키고 재귀호출
}
int main(void)
{
    cin >> num;
    for (int i = 0; i < num; i++)
    {
        int wi, hi;
        cin >> wi >> hi;
        man.push_back(pair<intint>(wi, hi));
    }
    Solution(0);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 6day

간단하게 등수를 저장할 ranking이라는 벡터를 정의하고 ranking에 등수를 담아 출력하였다.

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

백준 14888번: 연산자 끼워넣기  (0) 2020.04.12
백준 6603번: 로또  (0) 2020.04.12
백준 14502번: 연구소  (0) 2020.04.11
백준 2231번: 분해합  (0) 2020.04.11
백준 14501번: 퇴사  (0) 2020.04.10


여러가지 고려해야할 점이 많아서 복잡해 보이지만 결국은 조합을 구하는 완전탐색 문제이다.

주어진 배열에서 3개의 0을 1로 바꾸는 모든 경우의 수를 구한다. --> N개의 원소에서 3개를 뽑는 경우의 수와 같음

바뀐 배열에서 2의 상하좌우에 존재하는 0을 2로 바꿔주고, 이 작업을 더이상 바꿀 수 없을 때 까지 반복한 다음 배열에서 0의 갯수를 구하여 가장 큰 값을 결과로 반환해주면 된다.


#include <iostream>
#include <cstring>
using namespace std;
 
 
int col, row;
int board[9][9];
bool visited[9][9];
 
int max(int a, int b) { return a > b ? a : b; }
 
int Solution(int startY, int wall)
{
    if (wall == 3)            // 기저사례. 벽을 3개 쌓았다면 2를 다 퍼뜨리고 값을 반환한다.
    {
        int temp[9][9];
        for (int i = 0; i < col; i++)
            for (int j = 0; j < row; j++)
                temp[i][j] = board[i][j];
 
        bool state = false;
        while (state == false)
        {
            state = true;
            for (int i = 0; i < col; i++)
                for (int j = 0; j < row; j++)
                    if (temp[i][j] == 2)
                    {
                        if (i > 0)    // 2 의 9시 방향
                            if (temp[i - 1][j] == 0)
                            {
                                temp[i - 1][j] = 2;
                                state = false;
                            }
                        if (j > 0)    // 2의 12시 방향
                            if (temp[i][j - 1== 0)
                            {
                                temp[i][j - 1= 2;
                                state = false;
                            }
                        if (i + 1 < col)    // 2의 6시 방향
                            if (temp[i + 1][j] == 0)
                            {
                                temp[i + 1][j] = 2;
                                state = false;
                            }
                        if (j + 1 < row)    // 2의 3시 방향
                            if (temp[i][j + 1== 0)
                            {
                                temp[i][j + 1= 2;
                                state = false;
                            }
                    }
        }
        int cnt = 0;
        for (int i = 0; i < col; i++)
            for (int j = 0; j < row; j++)
                if (temp[i][j] == 0) cnt++;
        return cnt;
    }
 
    int ret = -1;
    for (int i = startY; i < col; i++)
    {
        for (int j = 0; j < row; j++)
        {
            if (board[i][j] == 0)
            {
                if (visited[i][j] == truecontinue;
                visited[i][j] = true;
                board[i][j] = 1;
                ret = max(ret, Solution(i, wall + 1));
                board[i][j] = 0;
                visited[i][j] = false;
            }
        }
    }
    return ret;
}
 
int main(void)
{
    cin >> col >> row;
    memset(visited, falsesizeof(visited));    // 배열 전체를 방문하지 않은상태로 초기화
    for (int i = 0; i < col; i++)
    {
        for (int j = 0; j < row; j++)
        {
            int n;
            cin >> n;
            board[i][j] = n;
        }
    }
    cout << Solution(0,0<< endl;
 
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 6day

다른 사람들이 푼 방식을 보니 바이러스를 확산시키는데 DFS, BFS를 사용했다.

나는 아직 DFS와 BFS에 대해 잘 모르는 상태라 다소 무식하게 풀어낸거 같다.

그 부분들을 공부하게 되면 다시한번 풀어보도록 해야겠다.

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

백준 6603번: 로또  (0) 2020.04.12
백준 7568번: 덩치  (0) 2020.04.11
백준 2231번: 분해합  (0) 2020.04.11
백준 14501번: 퇴사  (0) 2020.04.10
백준 2309번: 일곱 난쟁이  (0) 2020.04.10

 

 


1~N까지 완전탐색을 돌려도 시간 제한에 걸리지 않는 문제지만 생성자의 한가지 규칙을 발견하여 적용시켰다.

각 자리수는 0~9의 값만 가지기 때문에 각 자리수의 합은 최대 9 * N을 넘지 못한다.

ex) 99->9+9=18, 999->9+9+9=27

분해합 = 생성자+자리수이므로 생성자의 최솟값은 (분해합 - (9*N)) 인 것을 알 수 있다. 


#include <iostream>
using namespace std;
 
int Solution(int num)
{
    int temp = num;
    int cnt = 1;
    while ((temp /= 10!= 0)
        cnt++;
    int start = num - (cnt * 9);
    for (int i = start; i < num; i++)
    {
        temp = i;
        int sum = temp;
        while (temp / 10 != 0)
        {
            sum += temp % 10;
            temp /= 10;
        }
        sum += temp;
        if (sum == num)
        {
            return i;
        }
    }
    return 0;
}
int main(void)
{
    int num;
    cin >> num;
    cout << Solution(num) << endl;
 
    return 0;
}
 
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

 

 

 

알고리즘 200일 프로젝트 - 5day

내일도 열심히!

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

백준 6603번: 로또  (0) 2020.04.12
백준 7568번: 덩치  (0) 2020.04.11
백준 14502번: 연구소  (0) 2020.04.11
백준 14501번: 퇴사  (0) 2020.04.10
백준 2309번: 일곱 난쟁이  (0) 2020.04.10

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 <vector>
using namespace std;
 
vector<int> time;
vector<int> pay;
int day;
int max(int a, int b) { return a > b ? a : b; }
int Solution(int start, int money)
{
    int ret = money;
    for (int i = start; i < day; i++)
    {
        int next = i + time[i];
        if (next > day) continue;
        ret = max(ret, Solution(next, money + pay[i]));   
    }
    return ret;
}
int main(void)
{
    cin >> day;
    for (int i = 0; i < day; i++)
    {
        int T, P;
        cin >> T >> P;
        time.push_back(T);
        pay.push_back(P);
    }
    cout << Solution(0,0<< endl;
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 5day

퇴사날이 0 <= day <= 15 라는 점을 이용하여 완전탐색으로 구현하는 간단한 문제였다.

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

백준 6603번: 로또  (0) 2020.04.12
백준 7568번: 덩치  (0) 2020.04.11
백준 14502번: 연구소  (0) 2020.04.11
백준 2231번: 분해합  (0) 2020.04.11
백준 2309번: 일곱 난쟁이  (0) 2020.04.10

[백준 2309번 일곱 난쟁이]

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
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
 
vector<int> picked;
vector<int> smallMan;
bool finish = true;
void findSmallMan(vector<int>& picked, int start ,int tallSum)
{
    if (finish == falsereturn;    // 기저사례. 이미 1번 출력했다면 함수를 빠져나온다.
    if (picked.size() == 7)
    {
        if (tallSum == 100)
        {
            sort(picked.begin(), picked.end());
            for (int i = 0; i < 7; i++)
                cout << picked[i] << endl;
            finish = false;
        }
    }
    for (int i = start; i < 9; i++)    // 순서만 다른 조합을 배제하기 위해 start부터 시작
    {
        picked.push_back(smallMan[i]);
        findSmallMan(picked, i + 1, tallSum + smallMan[i]);
        picked.pop_back();
    }
}
int main(void)
{
    for (int i = 0; i < 9; i++)
    {
        int tall;
        cin >> tall;
        smallMan.push_back(tall);
    }
    findSmallMan(picked, 00);
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 5day

원소의 수가 9개로 제한되어 있기때문에 완전탐색 알고리즘을 적용하여 간단하게 해결할 수 있는 문제였다.

 

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

백준 6603번: 로또  (0) 2020.04.12
백준 7568번: 덩치  (0) 2020.04.11
백준 14502번: 연구소  (0) 2020.04.11
백준 2231번: 분해합  (0) 2020.04.11
백준 14501번: 퇴사  (0) 2020.04.10

출처: 알고스팟

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
#include <iostream>
#include <vector>
using namespace std;
 
#define INF 987654321
 
vector<vector<int> > switch_list({        // 스위치와 연결된 시계
    vector<int>({ 012 }),
    vector<int>({ 37911 }),
    vector<int>({ 4101415 }),
    vector<int>({ 04567 }),
    vector<int>({ 6781012 }),
    vector<int>({ 021415 }),
    vector<int>({ 31415 }),
    vector<int>({ 4571415 }),
    vector<int>({ 12345 }),
    vector<int>({ 345913 })
    });
 
int min(int a, int b) { return a < b ? a : b; }
 
void SetTheClock(vector<int>& watch, int swtch)
{
    int n = switch_list[swtch].size();
    for (int i = 0; i < n; i++)
    {
        watch[switch_list[swtch][i]] += 3;
        if (watch[switch_list[swtch][i]] > 12)
            watch[switch_list[swtch][i]] = 3;
    }
}
 
int twelveOclock(vector<int>& watch, int swtch)
{
    if (swtch == 10)
    {
        for (int i = 0; i < 16; i++)
            if (watch[i] != 12return INF;
        return 0;
    }
    int ret = INF;
    for (int cnt = 0; cnt < 4; cnt++)
    {
        ret = min(ret, cnt + twelveOclock(watch, swtch+1));    // 시계 돌려돌려
        SetTheClock(watch, swtch);
    }
    return ret;
}
 
int main(void)
{
    int testcase;
    vector<int> watch;
    cin >> testcase;
    while (testcase--)
    {
        for (int i = 0; i < 16; i++)
        {
            int time;
            cin >> time;
            watch.push_back(time);
        }
        int res = twelveOclock(watch, 0);
        if (res == INF) cout << -1 << endl;
        else cout << res << endl;
        watch.clear();
    }
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter

알고리즘 200일 프로젝트 - 4day

알고리즘 문제해결 전략 6.8 시계 맞추기(ID:CLOCKSYNC)

난이도 중짜리 문제였지만 내가 생각한 아이디어와 책에서 제시한 풀이법이 같아서 뿌듯했다.

하지만 시계를 4번 움직였을 때 제자리로 돌아온다는 점을 생각은 했으나 문제의 핵심포인트라는 것까지는 생각하지 못하여 원하는 출력결과를 얻지못하였다. 성급하게 구현하는 나쁜습관을 고치도록 노력해야겠다.

또한 아무리 들여봐도 알 수없는 버그때문에 골머리를 앓았는데 그 원인은 허무하게도 첫줄의 벡터배열을 잘못된 방법으로 선언함으로써 발생한 버그였다.

종만북 공부를 잠시 중단하고 effective c++과 뇌를 자극하는 c++ STL 두 권을 먼저 공부 한다음 다시 펼쳐봐야겠다.

내일도 열심히!

 
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
#include <iostream>
#include <vector>
using namespace std;
int cnt;
const int coverType[4][3][2= {
    {{0,0}, {0,1}, {1,1}},    // 블록이 회전하는 4가지 형태 
    {{0,0}, {1,0}, {1,1}},
    {{0,0}, {1,0}, {1,-1}},
    {{0,0}, {0,1}, {1,0}}
};
bool set(vector<vector<int> >& board, int y, int x, int type, int delta)
{
    bool state = true;
    for (int i = 0; i < 3; i++)
    {
        int colMax = board.size();
        int rowMax = board[0].size();
        const int ny = y + coverType[type][i][0];
        const int nx = x + coverType[type][i][1];
        if (ny < 0 || ny >= colMax ||
            nx < 0 || nx >= rowMax)
            state = false;
        else if ((board[ny][nx] += delta) > 1)    // delta = 1 일 때, 블록을 덮는다. 
            state = false;                        // delta = -1 일 때, 블록을 치운다. 
    }
    return state;
}
int Solution(vector<vector<int> >& board)
{
    if (cnt % 3 != 0return 0;    // 기저 사례. 비어이는 블록의 수가 3의 배수가 아닐 경우 반드시 실패
    int col = -1, row = -1;
    int colMax = board.size();    // 행 길이
    int rowMax = board[0].size();    // 열 길이
    for (int i = 0; i < colMax; i++)
    {
        for (int j = 0; j < rowMax; j++)    // 비어있는 칸 중 좌측 상단을 먼저 
        {
            if (board[i][j] == 0)
            {
                col = i;
                row = j;
                break;
            }
        }
        if (col != -1break;    // 2중 for문 탈출 
    }
    if (col == -1return 1;    // 기저 사례. 비어있는 칸이 없으므로 1 증가
    int ret = 0;
    for (int i = 0; i < 4; i++)
    {
        if (set(board, col, row, i, 1))    // 비어있는 칸에 블록을 맞춰본다 
            ret += Solution(board);
        set(board, col, row, i, -1);
    }
    return ret;
}
int main(void)
{
    int testcase;
    cin >> testcase;
    while (testcase--)
    {
        int a, b;
        cin >> a >> b;
        vector<vector<int>> board(a);
        cnt = 0;
        for (int i = 0; i < a; i++)
        {
            for (int j = 0; j < b; j++)
            {
                char block;
                cin >> block;
                if (block == '#')    // 막힌 칸을 1로 치환 
                    board[i].push_back(1);
                else if (block == '.')    // 비어있는 칸을 0으로 치환 
                {
                    board[i].push_back(0);
                    cnt++;
                }
            }
        }
        cout << Solution(board) << endl;
        board.clear();
    }
    return 0;
}
http://colorscripter.com/info#e" target="_blank" style="color:#4f4f4ftext-decoration:none">Colored by Color Scripter
 
 

 

 

알고리즘 200일 프로젝트 - 4day

알고리즘 문제해결 전략 6.5 게임판 덮기(ID:BOARDCOVER)

피크닉 문제에서 적용한 재귀함수와 유사한 형태로 구현할 수 있는 문제였다.

내가 생각한 아이디어와 책에서 제시한 아이디어의 접근방법은 비슷했으나,

중복을 신경쓰지 못하여 원하는 출력을 얻지 못하였다. 꾸준히 복습하여 내것으로 만들도록 해야겠다. 

내일도 열심히!

 

 

+ Recent posts