Skip to content

Commit 5ae698a

Browse files
authored
Merge pull request #18 from bsa0322/sua4
[브루트포스] 03월 20일 (선택 5개 CPP)
2 parents fc95372 + c529580 commit 5ae698a

File tree

8 files changed

+481
-0
lines changed

8 files changed

+481
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <iostream>
2+
#include <vector>
3+
4+
using namespace std;
5+
6+
const int SIZE = 64; //체스판 칸 개수
7+
8+
//(x, y)에서 시작하는 8*8 체스판을 만드는데 필요한 최소 카운트 리턴
9+
//검정으로 시작하는 체스판을 기준으로 계산(b_count) -> 절반(32) 이상이면 흰색으로 시작하는 체스판 카운트(64 - b_count) 리턴
10+
int chessChange(int row, int col, vector<vector<char>> &board) {
11+
int b_cnt = 0; //B로 시작하는 체스판 만들기 위한 카운트
12+
13+
for (int i = 0; i < 8; i++) { //행 변화값
14+
for (int j = 0; j < 8; j++) { //열 변화값
15+
if ((i + j) % 2 == 0 && board[row + i][col + j] != 'B') {
16+
b_cnt++;
17+
} else if ((i + j) % 2 && board[row + i][col + j] != 'W') {
18+
b_cnt++;
19+
}
20+
21+
}
22+
}
23+
24+
//최솟값 리턴
25+
if (b_cnt > SIZE / 2) {
26+
return SIZE - b_cnt;
27+
}
28+
return b_cnt;
29+
}
30+
31+
/**
32+
* [체스판 다시 칠하기]
33+
* - 나올 수 있는 체스판의 경우: 2가지
34+
* - (0, 0)이 검정인 경우, 흰색인 경우
35+
* - 검정으로 시작하는 체스판의 경우, 인덱스 i+j가 짝수일 때 'B'임을 이용
36+
*
37+
* 1. (0, 0) 인덱스부터 차례로 8*8 체스판 만들 때 바꿔야 하는 칸 수를 계산하고, 그 중 최솟값 구하기
38+
*
39+
* 보드 크기 <= 2,500
40+
* 한 위치에 대한 체스판 비교 연산 = 64번
41+
* 총 연산 수 = 2,500 * 64 < 1억 -> 브루트 포스 가능
42+
*/
43+
44+
int main() {
45+
int n, m;
46+
int ans = SIZE + 1; //정답은 체스판 칸 개수 + 1 로 초기화
47+
48+
//입력
49+
cin >> n >> m;
50+
vector<vector<char>> board(n, vector<char>(m)); //행: n, 열: m
51+
for (int i = 0; i < n; i++) { //보드 입력
52+
for (int j = 0; j < m; j++) {
53+
cin >> board[i][j];
54+
}
55+
}
56+
57+
//연산
58+
for (int i = 0; i <= n - 8; i++) {
59+
for (int j = 0; j <= m - 8; j++) {
60+
int cnt = chessChange(i, j, board); //시작인덱스가 (i,j)인 체스판 만드는 최솟값
61+
ans = min(ans, cnt); //최솟값 갱신
62+
}
63+
}
64+
65+
//출력
66+
cout << ans << '\n';
67+
return 0;
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#include <iostream>
2+
#include <algorithm>
3+
#include <vector>
4+
#include <map>
5+
6+
using namespace std;
7+
8+
map<char, bool> vowels; //모음 저장 맵
9+
10+
//조합 임시배열로 문자열을 만드는 함수
11+
string charToString(int c, vector<char> &alphabet, vector<bool> &is_in_password) {
12+
string result = "";
13+
for (int i = 0; i < c; i++) {
14+
if (is_in_password[i]) { //연산에 포함된 문자라면 result에 더하기
15+
result += alphabet[i];
16+
}
17+
}
18+
return result;
19+
}
20+
21+
//암호 만들기 가능한지 확인하는 함수 (최소 모음 1개, 최소 자음 2개)
22+
bool isValid(int l, int c, vector<char> &alphabet, vector<bool> &is_in_password) {
23+
int cnt_vowels = 0;
24+
//자음 개수는 암호 전체 길이에서 모음 개수를 빼서 알 수 있음
25+
for (int i = 0; i < c; i++) {
26+
if (!is_in_password[i]) { //암호에 속하지 않았다면
27+
continue;
28+
}
29+
if (vowels[alphabet[i]]) { //모음이라면
30+
cnt_vowels++;
31+
}
32+
}
33+
return (cnt_vowels >= 1) && ((l - cnt_vowels) >= 2);
34+
}
35+
36+
//조합 구하기
37+
vector<string> findPassword(int l, int c, vector<char> &alphabet) {
38+
vector<string> result;
39+
vector<bool> is_in_password(c, false);
40+
for (int i = 0; i < l; i++) { //미리 l개의 true 저장
41+
is_in_password[i] = true;
42+
}
43+
do {
44+
if (isValid(l, c, alphabet, is_in_password)) { //암호 만들기 가능하다면
45+
result.push_back(charToString(c, alphabet, is_in_password));
46+
}
47+
} while (prev_permutation(is_in_password.begin(), is_in_password.end()));
48+
49+
return result;
50+
}
51+
52+
/**
53+
* [암호 만들기]
54+
* 알파벳은 최대 15개 -> 브루트포스 가능
55+
* 가능한 모든 조합 만들어서, 검사 통과하면 출력
56+
*/
57+
58+
int main() {
59+
int l, c;
60+
61+
//모음 저장
62+
vowels['a'] = vowels['e'] = vowels['i'] = vowels['o'] = vowels['u'] = true;
63+
64+
//입력
65+
cin >> l >> c;
66+
vector<char> alphabet(c, 0);
67+
for (int i = 0; i < c; i++) {
68+
cin >> alphabet[i];
69+
}
70+
71+
//연산
72+
sort(alphabet.begin(), alphabet.end()); //오름차순 정렬
73+
vector<string> result = findPassword(l, c, alphabet);
74+
75+
//출력
76+
for (int i = 0; i < result.size(); i++) {
77+
cout << result[i] << '\n';
78+
}
79+
return 0;
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <iostream>
2+
#include <algorithm>
3+
4+
using namespace std;
5+
6+
int l, c; //l:암호 길이, c: 주어지는 문자 개수
7+
bool is_vowel[26]; //모음 체크
8+
char alpha[20];
9+
10+
void makeCypher(int cnt, int start, int vowel_cnt, string password) {
11+
if (cnt == l) { //암호의 길이만큼 수를 만들면 (기저조건)
12+
if (vowel_cnt >= 1 && (cnt - vowel_cnt) >= 2) { //조건(모음 최소 1개, 자음 최소 2걔)에 맞다면 출력
13+
cout << password << '\n';
14+
}
15+
return;
16+
}
17+
for (int i = start; i < c; i++) {
18+
if (is_vowel[alpha[i] - 'a']) { //모음이라면
19+
makeCypher(cnt + 1, i + 1, vowel_cnt + 1, password + alpha[i]); //모음수 카운트
20+
}
21+
else {
22+
makeCypher(cnt + 1, i + 1, vowel_cnt, password + alpha[i]);
23+
}
24+
}
25+
}
26+
27+
/**
28+
* [재귀함수 풀이] (0ms)
29+
* 매개변수로 시작위치를 보내줘서 오름차순 암호만 검사하도록 가지치기 진행 (N과 M(2)와 동일)
30+
* 매개변수로 암호 속에 포함된 모음 개수 카운트해서 조건 만족하지 않으면 가지치기 진행
31+
* 매개변수로 password 보내주면서 암호 만들어나감
32+
*/
33+
34+
int main() {
35+
//입력
36+
cin >> l >> c;
37+
for (int i = 0; i < c; i++) {
38+
cin >> alpha[i];
39+
}
40+
41+
//모음 저장
42+
is_vowel['a' - 'a'] = is_vowel['e' - 'a'] = is_vowel['i' - 'a'] = is_vowel['o' - 'a'] = is_vowel['u' - 'a'] = true;
43+
44+
//연산
45+
sort(alpha, alpha + c); //암호를 미리 오름차순으로 정렬
46+
47+
//연산 + 출력
48+
//차례로 암호 길이, 시작 위치, 모음 개수, 암호에 대한 매개변수
49+
makeCypher(0, 0, 0, "");
50+
51+
return 0;
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <cmath>
4+
5+
using namespace std;
6+
7+
int findMinNumber(int n, int num_size, vector<int> &square_num) {
8+
if (square_num[num_size - 1] == n) { //1개로 만들 수 있을 경우 바로 리턴
9+
return 1;
10+
}
11+
for (int i = num_size - 1; i >= 0; i--) { //2개로 만들 수 있는 경우 검사
12+
for (int j = num_size - 1; j >= 0; j--) {
13+
if (square_num[i] + square_num[j] == n) {
14+
return 2;
15+
}
16+
}
17+
}
18+
for (int i = num_size - 1; i >= 0; i--) { //3개로 만들 수 있는 경우 검사
19+
for (int j = num_size - 1; j >= 0; j--) {
20+
for (int k = num_size - 1; k >= 0; k--) {
21+
if (square_num[i] + square_num[j] + square_num[k] == n) {
22+
return 3;
23+
}
24+
}
25+
}
26+
}
27+
return 4;
28+
}
29+
30+
/**
31+
* [Four Squares] - 브루트포스 풀이 (8ms)
32+
* 자연수 n에 대해 최소 몇개의 제곱수의 합으로 표현할 수 있는지 찾는 문제
33+
* 미리 최댓값까지의 제곱수를 구해놓고, 완전탐색
34+
*
35+
* 1 ~ 3개 조합으로 불가능한 경우, 답은 무조건 4가 된다 -> 4개의 합은 시도해보지 않아도 된다.
36+
*
37+
* sqrt(50000) = 약 223
38+
* 전체 연산 수 < 223^2 + 223^3 = 11139296 <1억 -> 브루트포스 가능
39+
*/
40+
41+
int main() {
42+
int n, num_size;
43+
vector<int> square_num;
44+
45+
//입력
46+
cin >> n;
47+
48+
//연산
49+
for (int i = 1; i <= sqrt(n); i++) { //미리 루트 n 까지의 제곱수 저장
50+
square_num.push_back(i * i);
51+
}
52+
num_size = square_num.size(); //제곱수 개수
53+
54+
//출력
55+
cout << findMinNumber(n, num_size, square_num);
56+
return 0;
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include <iostream>
2+
#include <vector>
3+
#include <cmath>
4+
5+
using namespace std;
6+
7+
int n, num_size;
8+
vector<int> square_num;
9+
10+
bool isPossible(int cnt, int sum, int m) { //cnt: 고른 개수, sum: 지금까지 합, m: 골라야 하는 개수
11+
bool check = false; //m개의 제곱수 합 표현 가능한지
12+
13+
if (cnt == m) { //다 골랐다면
14+
if (sum == n) { //제곱수 합이 n과 같다면
15+
return true;
16+
}
17+
return false;
18+
}
19+
for (int i = num_size - 1; i >= 0; i--) {
20+
if (sum + square_num[i] <= n) {
21+
check = isPossible(cnt + 1, sum + square_num[i], m);
22+
if (check) { //m개의 제곱수의 합 표현 가능
23+
return true;
24+
}
25+
}
26+
}
27+
return check;
28+
}
29+
30+
/**
31+
* [Four Squares] - 백트래킹 풀이 (8ms)
32+
* 자연수 n에 대해 최소 몇개의 제곱수의 합으로 표현할 수 있는지 찾는 문제
33+
* 미리 최댓값까지의 제곱수를 구해놓고, 1개 ~ 3개까지의 제곱수 합으로 표현이 가능한지 검사
34+
* 이때, 제곱수가 큰 수부터 검사해서 더한 값이 n 넘어가면 가지치기
35+
*
36+
* 1. 1 ~ 3개의 조합으로 불가능한 경우, 답은 무조건 4가 된다 -> 4개의 합은 시도해보지 않아도 된다.
37+
*/
38+
39+
int main() {
40+
//입력
41+
cin >> n;
42+
43+
//연산
44+
for (int i = 1; i <= sqrt(n); i++) { //미리 루트 n 까지의 제곱수 저장
45+
square_num.push_back(i * i);
46+
}
47+
num_size = square_num.size(); //제곱수 개수
48+
49+
//3개의 조합까지만 구함
50+
int ans = 4; //우선 4로 초기화
51+
for (int i = 1; i <= 3; i++) {
52+
if (isPossible(0, 0, i)) { //정답 생기면
53+
ans = i;
54+
break;
55+
}
56+
}
57+
58+
//출력
59+
cout << ans;
60+
return 0;
61+
}

0 commit comments

Comments
 (0)