[BOJ] 브루트 포스

2020. 7. 30. 09:10BOJ

오늘부터는 (시시한 거 그만하고) 슬슬 알고리즘을 해보도록 하겠습니다. 오늘의 주제는 브루트 포스입니다. 브루트 포스는 그냥 무식하게 하나하나 다 해보는 방법입니다. 한마디로 난 그런 거 잘 모르겠고 일단 부딪혀.

 

[BOJ 2798]

 

3개의 카드를 고르는 경우를 모두 해보는 방법입니다. 3개의 카드를 고르기 때문에 3중 for문입니다.

#include <stdio.h>
#include <vector>

using namespace std;

int nearestsum(const vector<int> & cards, int limit){
    int maxsum = 0;
    for(int i=0;i<cards.size();++i)
    for(int j=i+1;j<cards.size();++j)
    for(int k=j+1;k<cards.size();++k){
        int newsum = cards[i] + cards[j] + cards[k];
        if(maxsum < newsum && newsum <= limit)
            maxsum = newsum;
    }
    return maxsum;
}

int main(){
    int N, M;
    scanf("%d%d",&N,&M);
    vector<int> cards(N);
    for(int k=0;k<N;++k)
        scanf("%d",&cards[k]);
    printf("%d",nearestsum(cards,M));
}

 

[BOJ 2231]

 

브루트 포스에 충실하게 숫자의 분해합을 구하는 함수를 짜고 하나씩 해보면서 값을 찾습니다.

#include <stdio.h>

int dividesum(int N){
    int divsum = N;
    while(N != 0){
        divsum += (N % 10);
        N /= 10;
    }
    return divsum;
}

int main(){
    int N;
    scanf("%d",&N);
    int m = 1;
    while(dividesum(m) != N && m<=N) m++;
    printf("%d", m<=N ? m : 0);
}

 

[BOJ 7568]

 

처음에는 이게 뭔가 싶었습니다. 결국에는 이 문장에 충실하게 해 주면 되겠습니다.

 

N명의 집단에서 각 사람의 덩치 등수는 자신보다 더 "큰 덩치"의 사람의 수로 정해진다. -본문 발췌-

 

한 명씩 덩치가 큰 사람을 세어주면 됩니다.

#include <stdio.h>
#include <vector>

using namespace std;

typedef pair<int, int> physical_t;

bool comparephysical(const physical_t & a, const physical_t & b){
    return ((a.first > b.first) && (a.second > b.second));
}

vector<int> physicalrank(const vector<physical_t> & P){
    vector<int> rank(P.size());
    for(int k=0;k<P.size();++k){
        int countsuperior = 0;
        const physical_t assess = P[k];
        for(const physical_t buddy : P){
            if(comparephysical(buddy, assess))
                countsuperior++;
        }
        rank[k] = countsuperior + 1;
    }
    return rank;
}

int main(){
    int N;
    scanf("%d",&N);
    vector<physical_t> P(N);
    for(int k=0;k<N;++k)
        scanf("%d%d", &P[k].first, &P[k].second);
    vector<int> rank = physicalrank(P);
    for(int k=0;k<N;++k) printf("%d ",rank[k]);
}

 

[BOJ 1018]

 

(0,0)에서 8x8을 잘랐을 때, (0,1)에서 8x8을 잘랐을 때,...

이렇게 자른 다음에 한 번씩 필요한 색칠의 개수를 세어주면 되겠습니다. 8x8을 복사하지 않고 배열 상에서 값을 얻어오도록 하게 위해 getval이라는 wrapper를 사용하였습니다. 그리고 한 가지 더 있는데요, 왼쪽 위가 검은색인 경우랑 흰색인 경우에 모든 칸의 색깔이 반대이기 때문에 각 경우에 색칠해야 하는 블록의 개수를 세면 합이 반드시 8x8의 총 칸의 개수인 64개입니다. 이를 이용해 주었습니다. 

#include <stdio.h>
#include <vector>

using namespace std;

typedef enum boardcolor_t{
    WHITE,
    BLACK,
    ERROR,
} boardcolor_t;

constexpr int BOARDSIZE = 8;
constexpr int BOARDBLOCKCOUNT = BOARDSIZE * BOARDSIZE;

typedef vector<vector<boardcolor_t>> chessboard_t;

class chessboardcut{
    public:
    const chessboard_t * Pboard;
    int offset_i, offset_j;
    int setoffset(int i, int j){
        offset_i = i;
        offset_j = j;
        return 0;
    }
    boardcolor_t getval(int i, int j){
        return (*Pboard)[offset_i+i][offset_j+j];
    }
    private:
    int colormodify(){
        int count = 0;
        for(int i=0;i<BOARDSIZE;++i)
        for(int j=0;j<BOARDSIZE;++j){
            // assume we will color upper left black
            boardcolor_t targetcolor = ((i+j)%2 == 0 ? BLACK : WHITE);
            if(targetcolor != getval(i, j))
                count++;
        }
        return (count <= (BOARDBLOCKCOUNT / 2) ? count : BOARDBLOCKCOUNT - count);
    }
    public:
    int mincolormodify(const chessboard_t & board){
        Pboard = &board;
        int sz_vert = board.size();
        int sz_hori = board[0].size();
        int minmodcount = BOARDBLOCKCOUNT;
        
        for(int i=0;i<sz_vert - BOARDSIZE + 1;++i)
        for(int j=0;j<sz_hori - BOARDSIZE + 1;++j){
            setoffset(i, j);
            int newmodcount = colormodify();
            if(minmodcount > newmodcount)
                minmodcount = newmodcount;
        }
        return minmodcount;
    }
};

int main(){
    int N, M;
    scanf("%d%d ",&N,&M);
    chessboard_t board;
    board.resize(N);
    for(int i=0;i<N;++i){
        board[i].resize(M);
        for(int j=0;j<M;++j){
            switch(getchar()){
                case 'W': board[i][j] = WHITE; break;
                case 'B': board[i][j] = BLACK; break;
                default: board[i][j] = ERROR; break;
            }
        }
        getchar(); // flush '\n'
    }
    chessboardcut C;
    printf("%d", C.mincolormodify(board));
}

 

[BOJ 1436]

 

당연하게도 더 쉽고 빠른 방법이 있겠지만 브루트 포스에 충실하게 해 주었습니다. 1부터 하나씩 올리면서 확인해줍니다. 

#include <stdio.h>

bool has666(int N){
    int countsix = 0;
    do {
        if(N % 10 == 6)
            countsix++;
        else
            countsix = 0;
        N /= 10;
        if(countsix >= 3)
            return true;
    } while(N != 0);
    return false;
}

int main(){
    int N;
    scanf("%d",&N);
    int nth_number;
    // stop at 10000th number
    for(int x=666, count=0;x<=2666799;x++){
        if(has666(x))
            count++;
        if(count == N){
            nth_number = x;
            break;
        }
    }
    printf("%d", nth_number);
}

 

감사합니다.^^

'BOJ' 카테고리의 다른 글

[BOJ] 재귀  (0) 2020.07.29
[BOJ 19533] [UCPC 2020 예선] 길이 문자열  (0) 2020.07.28
[BOJ] 수학 2(2)  (0) 2020.07.25
[BOJ] 수학 2(1)  (0) 2020.07.25
[BOJ] 수학 1(2)  (0) 2020.07.24