문제 출처: https://www.acmicpc.net/problem/1916


풀이

일반적인 다익스트라구현은O(V^2)이고, 우선순위큐를 활용한 다익스트라구현은 O(ElogV)인데, 입력범위를 보면

v^2=1,000,000이고, 2^10은 1024이므로 대략 ElogV=1,000,000쯤이므로 어떠한 방법을 사용하던지 pass를 받을 수 있습니다.

저는 우선순위큐를 이용한방법으로 풀었습니다. 

주의할 것은, "a에서 b로 가는길이 있다는것은 b에서 a로 가는길이 있다" 를 의미하는게 아니므로, 이 문제는

무방향그래프가 아닌 방향그래프입니다. 그것말고는 딱히 주의할것은 없는 것 같습니다.


코드

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int INF = 100000000;
vector < pair<int, int>>a[1001];
int d[1001];
void dijkstra(int start);
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	int n, m, v1, v2, w, start, end;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		d[i] = INF;

	for (int i = 0; i < m; i++)
	{
		cin >> v1 >> v2 >> w;
		a[v1].push_back(make_pair(v2, w));
	}
	cin >> start >> end;
	dijkstra(start);
	
	cout << d[end] << '\n';
}
void dijkstra(int start)
{
	d[start] = 0;
	priority_queue<pair<int, int>>pq;
	pq.push({ 0, start });
	while (!pq.empty())
	{
		int current = pq.top().second;
		int distance = -pq.top().first;
		pq.pop();
		//최단거리가 아니면 skip
		if (d[current] < distance)
			continue;
		for (int i = 0; i < a[current].size(); i++)
		{
			int next = a[current][i].first;
			int next_distance = distance + a[current][i].second;
			if (d[next] > next_distance)
			{
				d[next] = next_distance;
				pq.push(make_pair(-next_distance, next));
			}

		}
	}
	
}


결과


'문제풀이(BOJ) > 다익스트라' 카테고리의 다른 글

[백준 1719] 택배  (0) 2020.01.24
[백준 1238] 파티  (0) 2020.01.24
[백준 1753] 최단경로  (0) 2020.01.22

문제출처: https://www.acmicpc.net/problem/1753

일반적인 선형탐색 다익스트라구현은 O(N^2)라 입력범위 때문에 당연히 시간초과가 뜰거라서, O(NlogN)방식의 풀이를 사용해야합니다.

우선순위큐를 활용한 방법이 있기때문에 그 방법을 사용했습니다.

모르시는분들은 손수 구현하기 힘드니 아래의 링크나 다른 자료들을 참고하시는게 좋을것 같습니다.!

https://jow1025.tistory.com/109

다익스트라를 구현하고 입력조건만 맞추면되므로 설명은 생략합니다.!


코드

#include<iostream>
#include<queue>
#include<vector>
int INF = 100000000;
using namespace std;

vector<pair<int, int>>a[20001];
int d[20001];
void dijkstra(int start);
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	int V, E, k, u, v, w;
	cin >> V >> E >> k;
	for (int i = 1; i <= V; i++)
		d[i] = INF;

	for (int i = 0; i < E; i++)
	{
		cin >> u >> v >> w;
		a[u].push_back(make_pair(v, w));
	}
	dijkstra(k);
	for (int i = 1; i <= V; i++)
	{
		if (d[i] == INF)
			cout << "INF" << '\n';
		else cout << d[i] << '\n';
	}

}
void dijkstra(int start)
{
	d[start] = 0;
	priority_queue<pair<int, int>>pq;
	pq.push(make_pair(0, start));
	while (!pq.empty())
	{
		int distance = -pq.top().first;
		int current = pq.top().second;
		pq.pop();
		if (d[current] < distance)
			continue;

		for (int i = 0; i < a[current].size(); i++)
		{
			int next = a[current][i].first;
			int next_distance = distance + a[current][i].second;
			if (d[next] > next_distance)
			{
				d[next] = next_distance;
				pq.push(make_pair(-next_distance, next));
			}
		}
	}
}


결과






'문제풀이(BOJ) > 다익스트라' 카테고리의 다른 글

[백준 1719] 택배  (0) 2020.01.24
[백준 1238] 파티  (0) 2020.01.24
[백준 1916] 최소비용 구하기  (0) 2020.01.23

문제출처: https://www.acmicpc.net/problem/2644


풀이

bfs를 이용하여 풀었습니다. a에서 b로 가는데 연결된 간선의 수가 정답이므로, check[]배열로  방문여부를 확인함과 동시에, 방문된 현재 좌표의 check배열값을 갱신하므로써 정답을 구할 수 있습니다. 주의할것은 14행,15행에서 최대 n=100까지 입력받기 때문에 32행에서 무의식적으로 i=0;i<n으로 조건을 작성하면 틀립니다. 범위 조심하셔야됩니다.


코드

#include<iostream>
#include<queue>
using namespace std;
int map[101][101];
int check[101];
int n, a, b, m, x, y, ans;
void bfs(int pos);
int main()
{
	cin >> n >> a >> b >> m;
	for (int i = 0; i < m; i++)
	{
		cin >> x >> y;
		map[x][y] = 1;
		map[y][x] = 1;
	}
	bfs(a);
	if (check[b] == 0)
		cout << -1 << endl;
	else
		cout << check[b] << endl;

}
void bfs(int pos)
{
	queue<int>q;
	q.push(pos);
	while (!q.empty())
	{
		int temp = q.front(); q.pop();
		//조심, i=0;i<n했으면 틀림
		for (int i = 1; i <=n; i++)
		{
			if(map[temp][i]&&check[i]==0)
			{
				check[i] = check[temp] + 1;
				q.push(i);
			}
		}
	}
}


결과



'문제풀이(BOJ) > DFS,BFS' 카테고리의 다른 글

[백준 17836] 공주님을 구해라!  (0) 2020.02.10
[백준 1759] 암호 만들기  (0) 2020.02.06
[백준 2589] 보물섬(BFS)  (0) 2020.01.17
[백준 14502] 연구소 (BFS)  (0) 2020.01.17
[백준 2667] 단지번호붙이기 (BFS)  (0) 2020.01.17

문제출처: https://www.acmicpc.net/problem/9663



구글에 백트래킹 검색해보시면 가장먼저 나오는게 n-queen 문제입니다.

기본적인 이해와 재귀호출을 정확히 이해해야하므로 학습하시고 올 것을 추천드립니다.

백트래킹의 대표적인 문제라서, 학습하시면 많은 소스코드들이있으니 풀이는 따로 적지않겠습니다.


코드

#include<iostream>
using namespace std;
int col[15];
int n, cnt;
void N_queen(int pos);
bool promising(int pos);
int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	cin >> n;
	N_queen(0);
	cout << cnt << '\n';
}
void N_queen(int pos)
{
	if (pos == n)
		cnt += 1;
	else
	{
		for (int i = 0; i < n; i++)
		{
			col[pos] = i;
			if (promising(pos))
				N_queen(pos + 1);
		}
	}
}
bool promising(int pos)
{
	for (int i = 0; i < pos; i++)
	{
		if (col[pos] == col[i] || abs(col[i] - col[pos]) == pos - i)
			return false;
	}
	return true;
}


결과

'문제풀이(BOJ) > 백트래킹' 카테고리의 다른 글

[백준 1182] 부분수열의 합  (0) 2020.02.09
[백준 6603] 로또  (0) 2020.02.05
[백준 14888] 연산자 끼워넣기  (0) 2020.01.20

문제출처: https://www.acmicpc.net/problem/14888


삼성전자 A형 기출문제입니다.


풀이

백트래킹을 이용하여 풀 수 있습니다.

cnt를 선언하여 숫자가 모두 사용되었는지 체크합니다.

최초에 일단 계산을 하려면 첫번째값이 필요하므로, 첫번째 값과 첫번째값이 사용되었음을 나타낼수 있게 cnt+1 두 변수를 매개변수로하는 함수를 선언하여 백트래킹으로 연산을 하면됩니다.


헷갈리시는 분들은 아래 경우처럼 식을 작게해서 이해하시고 식으로 표현해보시면좋을 것같습니다.



3

1 2 3

1 0 1 0


코드

#include<iostream>
#include<algorithm>
using namespace std;
int min_val = 1000000001;
int max_val = -1000000001;
int arr[12];
int op[4];
int n;
void func(int num, int cnt);
int main()
{
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> arr[i];
	for (int i = 0; i < 4; i++)
		cin >> op[i];
	//첫 숫자와
	int num = arr[0];
	//첫숫자를 배치하고 연산할준비하므로
	//ex)"1+" 상태여서 숫자한개썼으므로 cnt=1로시작
	func(num, 1);
	cout << max_val << endl << min_val << endl;

}
void func(int num, int cnt)
{
	//숫자를 다 썼으면
	if (cnt == n)
	{
		max_val = max(max_val, num);
		min_val = min(min_val, num);
		return;
	}
	//모든 연산자돌면서확인
	for (int i = 0; i < 4; i++)
	{
		//연산자가 있을 때만 연산합시다.
		if (op[i]) {
			if (i == 0)
			{
				//연산 할거기때문에 연산자 횟수-1
				op[i]--;
				//현재값과 현재 더해야하는 피연산자의 index더함
				func(num + arr[cnt], cnt + 1);
				//백트래킹
				op[i]++;
			}
			if (i == 1)
			{
				op[i]--;
				func(num - arr[cnt], cnt + 1);
				op[i]++;
			}
			if (i == 2)
			{
				op[i]--;
				func(num * arr[cnt], cnt + 1);
				op[i]++;
			}
			if (i == 3)
			{
				op[i]--;
				func(num / arr[cnt], cnt + 1);
				op[i]++;
			}
		}
	}
}


결과




'문제풀이(BOJ) > 백트래킹' 카테고리의 다른 글

[백준 1182] 부분수열의 합  (0) 2020.02.09
[백준 6603] 로또  (0) 2020.02.05
[백준 9663] N-Queen  (0) 2020.01.20

문제출처: https://www.acmicpc.net/problem/11444


행렬의 곱셈을 이용하여 분할정복 기법으로 푸는 문제입니다.

아래 링크에서 행렬곱셈을 이용한 접근방법에대해 공부하시고 풀 것을추천드립니다.

https://jow1025.tistory.com/101


풀이

입력값이 0일 때 0이출력되게끔만 해주면되고, 범위가 크기때문에 행렬을 담는변수, 입력 변수를 long long 형으로 선언해야합니다.

풀이는 행렬곱셈만할줄 알면되므로 생략하겠습니다.


코드

#include<iostream>
struct M
{
	long long data[2][2];
};
using namespace std;
long long fibo(long long x);
M divide(M a, long long x);
M multiply(M a, M b);
int main()
{
	long long n;
	cin >> n;
	if (n == 0) { cout << 0 << endl; return 0; }
	cout << fibo(n) << endl;
}
long long fibo(long long x)
{

	M a;
	a.data[0][0] = 1; a.data[0][1] = 1;
	a.data[1][0] = 1; a.data[1][1] = 0;
	a = divide(a, x);
	return a.data[0][1];
}
M divide(M a, long long  x)
{
	if (x > 1)
	{
		a = divide(a, x / 2);
		a = multiply(a, a);
		if (x % 2 == 1)
		{
			M b;
			b.data[0][0] = 1; b.data[0][1] = 1;
			b.data[1][0] = 1; b.data[1][1] = 0;
			a = multiply(a, b);
		}
	}
	return a;
}
M multiply(M a, M b)
{
	M c;
	c.data[0][0] = (a.data[0][0] * b.data[0][0] + a.data[0][1] * b.data[1][0])%1000000007;
	c.data[0][1] = (a.data[0][0] * b.data[0][1] + a.data[0][1] * b.data[1][1]) % 1000000007;
	c.data[1][0] = (a.data[1][0] * b.data[0][0] + a.data[1][1] * b.data[1][0]) % 1000000007;
	c.data[1][1] = (a.data[1][0] * b.data[0][1] + a.data[1][1] * b.data[1][1]) % 1000000007;
	return c;

}


결과

'문제풀이(BOJ) > 수학' 카테고리의 다른 글

[백준 11051] 이항 계수 2  (0) 2020.02.10
[백준 1339] 단어 수학  (0) 2020.02.09
[백준 1448] 삼각형 만들기  (0) 2020.01.13
[백준 2355] 시그마  (0) 2020.01.13
[백준2502] 떡 먹는 호랑이  (0) 2019.12.18

문제출처: https://www.acmicpc.net/problem/5533


풀이

구현력이 코딩테스트에서 제일중요한데 이런문제를 오래고민하고있는 제가 너무답답하네요 ㅠㅠ 평소에 이런 구현 연습 많이 하세요..

생각이 코딩으로 이어지는게 참 어려운것같네요.


오래 고민한만큼 상세하게 주석을 달아놨습니다. 설명은 이거로 대체할게요~


코드

#include<iostream>
using namespace std;
int card[200][3];
int score[200];
int main()
{
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> card[i][0] >> card[i][1] >> card[i][2];

	//총 3명이 연산하므로 
	for (int i = 0; i < 3; i++)
	{
		//3명이 각 점수에대해 n명과 비교
		//비교는 한명씩 탐색한다(버블정렬처럼)
		//총 3*n*n번 연산하게됨
		//j가 각 인원의 번호가됨.
		for (int j = 0; j < n; j++)
		{
			//현재 card[j][i]값과 같은게 있는지확인위해 check선언
			bool check_same = false;
			for (int k = 0; k < n; k++)
			{
				//본인은 비교에서 빼자(같은값이 있게되므로)
				if (j == k)continue;
				//같은값이있으면 탈출, 33행 안하므로 0값가짐
				if (card[j][i] == card[k][i])
				{
					check_same = true;
					break;
				}
			}
			//같지않다면 더해줌
			if (!check_same)
				score[j] += card[j][i];
		}
	}
	for (int i = 0; i < n; i++)
		cout << score[i] << endl;
}


결과


문제출처: https://www.acmicpc.net/problem/9517


풀이

dfs,bfs문제만 풀다가 머리도 식힐겸 시뮬레이션 문제를 풀어봤습니다.

각 사람의 시간과, 질문 대답여부를 pair로 받고 질문의 갯수동안 폭탄넘기기를 실행합니다. 주의할것은 8번까지왔는데 폭탄이 안터졌다면 1번으로 다시 가야하므로 이것만 조심하면됩니다.


코드

#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int k, n;
	//페어로 받자
	pair<int, char>p;
	cin >> k >> n;
	int sum = 0;
	for (int i = 0; i < n; i++)
	{
		cin >> p.first >> p.second;
		//sum>=210일때 탈출
		sum += p.first;
		if (sum >= 210)
			break;
		//질문답했다면 폭탄넘김
		if (p.second == 'T')
			k++;
		if (k > 8)
			k %= 8;
			
	}
	cout << k << endl;
	
}


결과

'문제풀이(BOJ) > 시뮬레이션(구현)' 카테고리의 다른 글

[백준 1018] 체스판 다시 칠하기  (0) 2020.02.07
[백준 5533] 유니크  (0) 2020.01.19
[백준 5567] 결혼식  (0) 2020.01.15
[백준 1120] 문자열  (0) 2020.01.09
[백준 2526] 싸이클  (0) 2020.01.09

+ Recent posts