- 백트래킹 -> 가지치기

- 완전탐색(브루트포스) -> for문/ 재귀 

- DFS -> 그래프탐색

 

//--------------------0802 - 백트래킹

//5국가 중 3국가 중복없이 선택(JKB != JBK) -> 조합
#include <iostream>
#include <string.h>
#include <cstring>
using namespace std;

char a[6] = "JKBSC";
char path[10];
int used[4];

void abc(int level, int st) {
	if (level == 3) {
		cout << path << endl;
		return;
	}

	for (int i = st; i < 5; i < i++) {
		if (used[i] == 1) continue;
		used[i] = 1;
		path[level] = a[i];
		abc(level + 1, i+1);
		used[i] = 0;
	}
	
}

int main() {
	
	abc(0,0);

	return 0;
}

//올림픽 금은동 J가 무조건 금 중복x // JKB != JBK -> 순열
#include <iostream>
#include <string.h>
#include <cstring>
using namespace std;

char a[5] = "JKBS";
char path[10];
int used[4];

void abc(int level) {
	if (level == 3) {
		if (path[0] == 'J')
			cout << path << endl;
		return;
	}

	for (int i = 0; i < 4; i < i++) {
		if (used[i] == 1) continue;
		used[i] = 1;
		path[level] = a[i];
		abc(level + 1);
		used[i] = 0;
	}

}

int main() {

	abc(0);

	return 0;
}

//h세로, w가로 - 각 세로라인에서 값 하나씩 선택(같은 세로라인 선택금지) 최소값 구하기
//4 4
//3 5 6 3
//1 -3 -6 1
//5 -7 -6 5
//1 1 5 4
 
#include <iostream>
using namespace std;

int w;
int h;
int map[10][10];
int mini = 21e8;
int used[10];

void run(int lev, int sum)
{
	if (lev == h) {
		if (sum < mini) mini = sum;

		if (sum == -9) {
			int d = 1;
		}
		return;
	}

	for (int i = 0; i < w; i++) {
		if (used[i] == 1) continue;
		used[i] = 1;
		run(lev + 1, sum + map[lev][i]);
		used[i] = 0;
	}

}

int main()
{
	freopen_s(new FILE *, "Text.txt", "r", stdin);
	cin >> h >> w;

	for (int y = 0; y < h; y++) {
		for (int x = 0; x < w; x++) {
			cin >> map[y][x];
		}
	}
	run(0, 0);
	cout << mini;

	return 0;
}


//n개의 좌표입력받아 *3 *2 *1하였을때 최대, 최소 구하기-------ⓗ
#include <iostream>
using namespace std;

int map[3][4] = {
	1, 2, 3, 4,
	5,4, -1, -2,
	-3, 0, 1, 2
};

int n = 3;
int used[3][4];

int maxi = -21e8;
int mini = 21e8;

void run(int lev, int sum)
{
	if (lev == n) {

		if (sum > maxi) maxi = sum;
		if (sum < mini) mini = sum;

		return;
	}

	for (int y = 0; y < 3; y++) {
		for (int x = 0; x < 4; x++) {
			if (used[y][x] == 1) continue;
			used[y][x] = 1;
			run(lev + 1, sum + (n - lev) * map[y][x]);
			used[y][x] = 0;
		}
	}

}

int main()
{
	//n 곳을 선택
	//같은 좌표 중복 선택 불가
	//3배, 2배, 1배 가중치 값 존재
	//합의 최댓값과 최솟값 둘다 출력하기

	run(0, 0);

	cout << maxi << endl;
	cout << mini << endl;

	return 0;
}

//direct 사용하여 대각선방향 합의 최대 구하기
#include <iostream>
using namespace std;

int map[5][6] = {
	1, 0, 2, 1, 2, 1,
	-1, 0, 1, 1, 2, 2,
	3, 3, 1, 2, 3, 4,
	5, 5, 5 ,3, 1, 2,
	1, 2, 3, 4, 0, 0
};

int directY[5] = { -1, -1, 1, 1, 0 };
int directX[5] = { -1, 1, -1, 1, 0 };

int getNum(int y, int x)
{
	int sum = 0;
	for (int t = 0; t < 5; t++) {
		int ny = y + directY[t];
		int nx = x + directX[t];
		if (ny < 0 || nx < 0 || ny >= 5 || nx >= 6) continue;
		sum += map[ny][nx];
	}
	return sum;
}

int main()
{
	//세 좌표를 입력받고
	//다섯 곳의 합을 구하는데
	//세 곳중 MAX값 출력

	int maxi = -21e8; //-21억
	for (int t = 0; t<3; t++) {
		int y, x;
		cin >> y >> x;

		int ret = getNum(y, x);
		if (maxi < ret) maxi = ret;

	}
	cout << maxi;

	return 0;
}


//배열에서 중복없이 세가지수 조합 -------------------->중요★
//2.재귀사용
#include <iostream>
#include <vector>
using namespace std;

vector<int> v = { 4, 5, 1, 7, 9, 2, 6 };
char path[10];

void run(int lev, int start)
{
	if (lev == 3) {
		cout << path << endl;
		return;
	}

	for (int i = start; i < v.size(); i++) {
		path[lev] = v[i] + '0';
		run(lev + 1, i + 1);
	}
}

int main()
{
	run(0, 0);

	return 0;
}

//1. 3중 for문 사용
#include <iostream>
#include <vector>
using namespace std;

vector<int> v = { 4, 5, 1, 7, 9, 2, 6 };

int main()
{
	for (int a = 0; a < v.size(); a++) {
		for (int b = a + 1; b < v.size(); b++) {
			for (int c = b + 1; c < v.size(); c++) {
				cout << v[a] << v[b] << v[c] << endl;
			}
		}
	}

	return 0;
}
 

// 백트래킹을 이용한 미로찾기------>추후 다시 다룰예정
#include <iostream>
#include <Windows.h>
using namespace std;

int map[8][8] = {
	0,1,0,0,1,0,0,0,
	0,1,0,0,0,0,1,0,
	0,0,0,0,1,1,1,0,
	0,1,1,0,1,0,1,0,
	0,1,0,0,0,0,1,0,
	0,0,0,0,1,1,0,0,
	0,1,1,0,1,1,0,1,
	0,1,1,0,1,0,0,0,
};

int used[8][8];
int direct[4][2] = { -1, 0, 1, 0, 0, 1, 0, -1 };

void print(int nowY, int nowX)
{
	system("cls");
	for (int x = 0; x < 10; x++) cout << "■";
	cout << endl;
	for (int y = 0; y < 8; y++) {
		cout << "■";
		for (int x = 0; x < 8; x++) {
			if (y == nowY && x == nowX) {
				cout << "★";
			}
			else if (map[y][x] == 0) {
				cout << "  ";
			}
			else {
				cout << "■";
			}
		}
		cout << "■";
		cout << endl;
	}
	for (int x = 0; x < 10; x++) cout << "■";
	Sleep(50);
}

void run(int nowY, int nowX)
{
	print(nowY, nowX);
	if (nowY == 7 && nowX == 7) {
		cout << "발견" << endl;
		system("color 1F");
		Sleep(1000);
		system("color 07");
		return;
	}

	for (int t = 0; t < 4; t++) {
		int ny = nowY + direct[t][0];
		int nx = nowX + direct[t][1];

		if (ny < 0 || nx < 0 || ny >= 8 || nx >= 8) continue;
		if (map[ny][nx] == 1) continue;
		if (used[ny][nx] == 1) continue;
		used[ny][nx] = 1;
		run(ny, nx);
		print(nowY, nowX);
		used[ny][nx] = 0;
	}

}

int main()
{
	used[0][0] = 1;
	run(0, 0);

	return 0;
}

//ABCD친구들이 영화관가는 경우의수 0~ABCD
#include<iostream>
using namespace std;
char path[10];
char name[3] = "ox";
char fri[5] = { "ABCD" };
void abc(int level)
{
	if (level == 4)
	{
		for (int x = 0; x < level; x++)
		{
			if (path[x] == 'o')cout << fri[x];
		}
		cout << endl;
		return;
	}
	for (int x = 0; x < 2; x++)
	{
		path[level] = name[x];
		abc(level + 1);
		path[level] = 0;
	}
}
int main()
{
	abc(0);
	return 0;
}

//A~입력받은 알파벳까지 중복제외 조합 모두출력 (AB 또는 BA처럼 연달아 출력 금지)
#include<iostream>
using namespace std;

char path[10];
char ch;
int used[100];

int abs(int v)
{
	if (v < 0) return -v;
	return v;
}

void run(int lev)
{
	if (lev >= 2 && abs(path[lev - 2] - path[lev - 1]) <= 1) return;

	if (ch - 'A' + 1 == lev) {
		cout << path << endl;
		return;
	}

	for (char c = 'A'; c <= ch; c++) {
		if (used[c] == 1) continue;
		used[c] = 1;
		path[lev] = c;
		run(lev + 1);
		used[c] = 0;
	}
}

int main()
{
	cin >> ch;

	run(0);

	return 0;
}

//설계후 구현하기 - 2차원 배열의 왼쪽과 위 비교후 작은값의 +3해서 완성하기
#include<iostream>
using namespace std;

int arr[4][6] = {
	{5,8,3,2,6,5},
	{4,0,0,0,0,0},
	{2,0,0,0,0,0},
	{6,0,0,0,0,0}, };

int main()
{

	for (int i = 1; i < 4; i++) {
		for (int j = 0; j < 5; j++) {
			if (arr[i][j] > arr[i - 1][j + 1])
				arr[i][j + 1] = arr[i - 1][j + 1] + 3;
			else {
				arr[i][j + 1] = arr[i][j] + 3;
			}
		}
	}

	for (int i = 0; i < 4; i++) {
		for (int j = 0; j < 6; j++) {
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}

//숫자카드에서 이웃하는 카드의 합 15미만
#include<iostream>
using namespace std;

int nums[5] = { 11, 5, 7, 4, 9 };
int path[10];

void run(int lev)
{
    if (lev >= 2 && path[lev - 2] + path[lev - 1] >= 15) return;

    if (lev == 4) {
        for (int i = 0; i < lev; i++) {
            cout << path[i] << " ";
        }
        //cout << endl;
        cout << "\n";
        return;
    }

    for (int i = 0; i < 5; i++) {
        //if (lev >= 1 && path[lev - 1] + nums[i] >= 15) continue;
        path[lev] = nums[i];
        run(lev + 1);
        path[lev] = 0; //옵션
    }
}


int main()
{
    run(0);
    

    return 0;
}

//n개의 주사위 합 10 이하인경우만 0+0+0=0 출력
#include<iostream>
using namespace std;

int n = 3;
char vect[10];

void run(int lev, int sum)
{
	if (sum > 10) return;

	if (lev == n) {
		int i = 0;
		for (i = 0; i < n - 1; i++) {
			cout << vect[i] << " + ";
		}
		cout << vect[i];
		cout << " = " << sum;
		cout << endl;
		return;
	}

	for (int i = 1; i <= 6; i++) {
		vect[lev] = '0' + i;
		run(lev + 1, sum + i);
	}

}

int main()
{
	run(0, 0);


	return 0;
}

'Algorithm > C++' 카테고리의 다른 글

[21.08.04]큐/스택 활용하기  (0) 2021.08.04
[21.08.03] dat활용 counting sort와 vector사용법  (0) 2021.08.03
[21.07.30] 재귀함수, 트리, DAT  (0) 2021.08.01
[21.07.29]스택, 큐  (0) 2021.08.01
[21.07.28] 문자열 파싱하기  (0) 2021.08.01

+ Recent posts