반응형

문제링크:https://www.acmicpc.net/problem/10825

 

10825번: 국영수

첫째 줄에 도현이네 반의 학생의 수 N (1 ≤ N ≤ 100,000)이 주어진다. 둘째 줄부터 한 줄에 하나씩 각 학생의 이름, 국어, 영어, 수학 점수가 공백으로 구분해 주어진다. 점수는 1보다 크거나 같고, 100보다 작거나 같은 자연수이다. 이름은 알파벳 대소문자로 이루어진 문자열이고, 길이는 10자리를 넘지 않는다.

www.acmicpc.net

 

그리디 알고리즘입니다. (사실 그리디라고도 할 수 없는 단순 정렬문제)

algorithm 라이브러리에 sort함수를 구현해 해결했습니다.

 

 

cmp는 오버라이딩 된 형태라 직접 구현할 수 있습니다. 

주석에 써놓은 번호순서대로 문제에서 요구하는 정렬을 구현한 것입니다. 

bool cmp(info a, info b) {
	if (a.korean > b.korean)  //1
		return true;
	else if(a.korean == b.korean){
		if (a.english < b.english) return true; //2
		else if(a.english == b.english){
			if (a.math > b.math) return true; //3
			else if(a.math == b.math) {
				if (a.name < b.name)return true; //4
			}
		}
	}

	return false;
}

 

처음에 시간초과가 났습니다. n = 100000 이고 sort 함수를 O(nlgn) 이기때문에 정렬의 문제는 아니였습니다. 

endl << 이 너무 많은 시간을 잡아먹어서 에러가 났었습니다. endl는 버퍼를 flush하는 역할을 겸하기 때문에 위 처럼 많은 출력을 해야해서 endl이 많이 사용될때는 endl사용을 지양하고 '\n'을 사용해야 합니다.

 

 

정답코드입니다.

 

#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
struct info {
	string name;
	int korean;
	int english;
	int math;
};

info arr[100001];
int n = 0;

/*
국어 점수가 감소하는 순서로
국어 점수가 같으면 영어 점수가 증가하는 순서로
국어 점수와 영어 점수가 같으면 수학 점수가 감소하는 순서로
모든 점수가 같으면 이름이 사전 순으로 증가하는 순서로 (단, 아스키 코드에서 대문자는 소문자보다 작으므로 사전순으로 앞에 온다.)
*/
bool cmp(info a, info b) {
	if (a.korean > b.korean)  //1
		return true;
	else if(a.korean == b.korean){
		if (a.english < b.english) return true; //2
		else if(a.english == b.english){
			if (a.math > b.math) return true; //3
			else if(a.math == b.math) {
				if (a.name < b.name)return true; //4
			}
		}
	}

	return false;
}
int main() {

	cin >> n;

	for (int i = 0; i < n; i++)
		cin >> arr[i].name >> arr[i].korean >> arr[i].english >> arr[i].math;

	sort(arr, arr + n, cmp);

	for (int i = 0; i < n; i++)
		cout << arr[i].name <<'\n';

}

 

꼭 직접 작성해보시기 바랍니다:) 화이팅

반응형

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

[백준] 1493-박스채우기(C++)  (0) 2020.05.19
[백준] 1092-배(C++)  (0) 2020.05.05
[백준] 8980-택배(C++)  (0) 2020.03.05
[백준] 1969-DNA(C++)  (0) 2020.03.03
[백준] 2437-저울(C++)  (0) 2020.03.03
반응형

문제링크:https://www.acmicpc.net/problem/14570

 

14570번: 나무 위의 구슬

이진 트리란, 위처럼 모든 노드의 자식의 수가 2개 이하인 트리이다. 각 노드에 쓰여 있는 수는 노드의 번호를 의미한다. 특히, 이 문제에서는 루트가 고정되어 있으며, 노드의 순서가 중요한(어떤 서브트리에서도 좌우를 변경할 수 없는) 이진 트리에 대해 다루기로 한다. 이진 트리의 루트에 구슬을 하나 올려놓으면 구슬은 아래와 같은 과정을 거쳐 떨어진다. 현재 구슬이 놓인 노드의 자식이 없다면 그 자리에서 멈춘다. 1을 만족하지 않으며, 만일 현재 구슬이 놓

www.acmicpc.net

 

간만에 털렸습니다...

우선 시뮬레이션 문제로 인식했습니다. 문제에서 요구하는 조건 그대로 이동하면서 결과값을 도출하게 끔 구현을 했습니다.

 

 

 

문제조건인 

  1. 현재 구슬이 놓인 노드의 자식이 없다면 그 자리에서 멈춘다.
  2. 1을 만족하지 않으며, 만일 현재 구슬이 놓인 노드의 자식 노드가 한 개라면 해당 자식 노드로 떨어진다.
  3. 1, 2를 만족하지 않으며, 만일 현재 구슬이 놓인 노드의 자식 노드가 두 개라면,
    1. 현재 노드의 왼쪽 서브트리에 담긴 모든 구슬의 수 <= 오른쪽 서브트리에 담긴 모든 구슬의 수일 경우, 왼쪽 자식 노드로 떨어진다.
    2. 그 외의 경우에는 오른쪽 자식 노드로 떨어진다.
  4. 1~3번의 조건을 다시 체크하고 되풀이한다.

를 생각하면서 구현한 답입니다.

 

#include <iostream>
using namespace std;

int n, u, v;
long long k;
int result = 0;
struct node {
	int left = 0;
	int right = 0;
};
node arr[200001];
int cnt[200001] = { 0 };
int left_cnt, right_cnt;

void add_cnt(int current,int direction) {
	
	if (arr[current].left == 0 && arr[current].left == 0) {
		if (direction == 0)
			left_cnt += cnt[current];
		else
			right_cnt += cnt[current];

		return;
	}
	if (arr[current].left != 0)  add_cnt(arr[current].left,direction);
	if (arr[current].right != 0)   add_cnt(arr[current].right, direction);

}

void action(int current,int i) {

	//1
	if (arr[current].left == 0 && arr[current].left == 0) {
		cnt[current]++;

		result = current;
		return;
	}
	//2
	else if ((arr[current].left != 0 && arr[current].right == 0)) action(arr[current].left,i);
	else if ((arr[current].left == 0 && arr[current].right != 0)) action(arr[current].right,i);
	//3
	else if (arr[current].left != 0 && arr[current].left != 0) {
		/*
		left_cnt = 0, right_cnt = 0;
		add_cnt(arr[current].left,0);
		add_cnt(arr[current].right,1);
		if(left_cnt <= right_cnt) action(arr[current].left);
		else action(arr[current].right);	
		*/

		if(i%2) action(arr[current].left,i/2 +1);
		else action(arr[current].right, i/2);
	}
}

int main() {

	cin >> n;

	for (int i = 1; i <= n; i++) {
		cin >> u >> v;
		if (u != -1 || v != -1) {
			arr[i].left = u;
			arr[i].right = v;
		}
	}

	cin >> k;

	for (int i = 1; i <= k; i++)
		action(1,i); //루트는 항상 1번 노드이다.

	cout << result << endl;
	
}

 

이러한 방식입니다. 문제가 많은 코드입니다. 

 

왜냐하면 1 ≤ K ≤ 10^18, 1 ≤ N ≤ 200000  이기 때문에 저렇게 무식한 시뮬레이션으로는 문제를 시간초과가 납니다.

 

규칙을 찾아야합니다. 

위와 같은 문제 규칙에서 2번, 4번, 2번, 5번, 2번 노드에 차례대로 떨어지게 됩니다. 

루트노드입장에서 생각해봅시다. k번째를 반복하며 인덱스가 홀수에서는 왼쪽 짝수에서는 오른쪽으로 이동합니다.

3의 입장에서도 보면 인덱스가 홀수에서는 왼쪽 짝수에서는 오른쪽으로 이동합니다. 

 

이러한 규칙이 있기 때문에 굳이 시뮬레이션할 필요가 없습니다.

즉 k번을 반복하는게 아니라, k번째만 확인해 답을 구할 수 있습니다.

 

 

정답코드입니다.

#include <iostream>
using namespace std;
struct node {
	int left, right;
};

node arr[200001];

int main() {
	int n; long long k;

	cin >> n;

	for (int i = 1; i <= n; i++)
		cin >> arr[i].left >> arr[i].right;

	cin >> k;

	int pos = 1; //루트 노드에서 시작
	while (1) {
		//1
		if (arr[pos].left == -1 && arr[pos].right == -1) break;
		//2
		else if (arr[pos].left == -1) pos = arr[pos].right; //왼쪽노드가 없음 -> 오른쪽으로 이동
		else if (arr[pos].right == -1) pos = arr[pos].left; //오른쪽노드가 없음 -> 왼쪽으로 이동
															//3
		else if (k % 2) {//1)조건 -> 홀수면 왼쪽으로 간다.
			pos = arr[pos].left, k = k / 2 + 1;
		}
		else { //2)조건 -> 짝수면 오른쪽으로 간다.
			pos = arr[pos].right, k /= 2;
		}
	}
	cout << pos << endl;

	return 0;
}

 

 

이중에서  아래 코드를 봅시다.

 

while (1) {
		//1
		if (arr[pos].left == -1 && arr[pos].right == -1) break;
		//2
		else if (arr[pos].left == -1) pos = arr[pos].right; //왼쪽노드가 없음 -> 오른쪽으로 이동
		else if (arr[pos].right == -1) pos = arr[pos].left; //오른쪽노드가 없음 -> 왼쪽으로 이동
															//3
		else if (k % 2) {//1)조건 -> 홀수면 왼쪽으로 간다.
			pos = arr[pos].left, k = k / 2 + 1;
		}
		else { //2)조건 -> 짝수면 오른쪽으로 간다.
			pos = arr[pos].right, k /= 2;
		}
	}

 

1,2번 조건은 쉽게 이해하실겁니다. 아래 코드에서 k%2와 k/2를 통해서 위치를 판별합니다. 

루트기준으로 k번째에서의 떨어지는 방향은 홀수면 왼쪽으로 짝수면 오른쪽으로 이동합니다. 

그아래 노드들도 위에서 설명한 규칙대로 이동하기 때문에 k값의 짝,홀수 를 변경해주는 것 입니다. 

반응형

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

[백준] 11000-강의실 배정(C++)  (0) 2021.05.25
[백준] 1068-트리(C++)  (0) 2021.05.21
[백준] 1436-영화감독 숌(C++)  (0) 2020.04.02
[백준] 3020-개똥벌레(C++)  (0) 2020.03.21
[백준] 15953-상금 헌터  (0) 2020.02.01
반응형

문제링크:https://www.acmicpc.net/problem/9205

 

9205번: 맥주 마시면서 걸어가기

문제 송도에 사는 상근이와 친구들은 송도에서 열리는 펜타포트 락 페스티벌에 가려고 한다. 올해는 맥주를 마시면서 걸어가기로 했다. 출발은 상근이네 집에서 하고, 맥주 한 박스를 들고 출발한다. 맥주 한 박스에는 맥주가 20개 들어있다. 목이 마르면 안되기 때문에 50미터에 한 병씩 마시려고 한다. 상근이의 집에서 페스티벌이 열리는 곳은 매우 먼 거리이다. 따라서, 맥주를 더 구매해야 할 수도 있다. 미리 인터넷으로 조사를 해보니 다행히도 맥주를 파는 편의

www.acmicpc.net

 

문제접근을 하는데 어려움을 겪었습니다.

처음에 가진 생각은 가장 이동경로내에 여러개의 편의점이 있으면 어디를 선택할까와 같은 생각을 했지만, 다시 생각해보니 무의미했습니다. yes, no로 도달할 수 있는지만 판단하면 되었기 때문입니다. 그렇기 때문에 모든 편의점을 탐색하며 도달할 수 있는지 여부만 판단했습니다.

 

bfs알고리즘을 사용해서 방문여부를 판단했습니다.

주의 하셔야 할 점은  두 좌표 사이의 거리는 x 좌표의 차이 + y 좌표의 차이 이다. (맨해튼 거리) 입니다.

문제를 꼼꼼히 읽는 습관을 가져야 합니다.

 

아래는 정답코드입니다.

#include <iostream>
#include <cstring>
#include <algorithm>
#include <math.h>
using namespace std;
int t = 0, n = 0;
int arr[101][2] = { 0 };
int starting_x, starting_y, destination_x, destination_y;
bool visited[101];
int que[1000000][2] = { 0 };
int started = 0, ended = 0;

void bfs() {
	que[ended][0] = starting_y;
	que[ended++][1] = starting_x;

	while (started != ended) {
		int y = que[started][0];
		int x = que[started++][1];

		for (int i = 0; i <= n; i++) {
			if (!visited[i]) {
				int len_x = min(abs(x - arr[i][1]), abs(arr[i][1] - x));
				int len_y = min(abs(y - arr[i][0]), abs(arr[i][0] - y));
				double len_total = len_x + len_y;
				if (len_total <= 1000)
				{
					visited[i] = 1;
					que[ended][0] = arr[i][0];
					que[ended++][1] = arr[i][1];
				}
				
			}
		}
	}

}
int main() {
	cin >> t;

	while (t--) {
		cin >> n;
		cin >> starting_x >> starting_y;
		for (int i = 0; i < n; i++)
			cin >> arr[i][1] >> arr[i][0];
		cin >> arr[n][1] >> arr[n][0];

		memset(visited, 0, sizeof(visited));
		started = 0, ended = 0;

		bfs();
		if (visited[n])
			cout << "happy" << endl;
		else
			cout << "sad" << endl;
	}


}
반응형

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

[백준] 8061-Bitmap  (0) 2020.03.26
[백준] 1389-케빈 베이컨의 6단계 법칙(C++)  (0) 2020.03.22
[백준] 5014-스타트링크(C++)  (1) 2020.03.12
[백준] 2589-보물섬(C++)  (0) 2020.03.08
[백준] 2644-촌수계산(C++)  (0) 2020.03.08
반응형

문제링크:https://www.acmicpc.net/problem/5014

 

5014번: 스타트링크

문제 강호는 코딩 교육을 하는 스타트업 스타트링크에 지원했다. 오늘은 강호의 면접날이다. 하지만, 늦잠을 잔 강호는 스타트링크가 있는 건물에 늦게 도착하고 말았다. 스타트링크는 총 F층으로 이루어진 고층 건물에 사무실이 있고, 스타트링크가 있는 곳의 위치는 G층이다. 강호가 지금 있는 곳은 S층이고, 이제 엘리베이터를 타고 G층으로 이동하려고 한다. 보통 엘리베이터에는 어떤 층으로 이동할 수 있는 버튼이 있지만, 강호가 탄 엘리베이터는 버튼이 2개밖에 없

www.acmicpc.net

 

 

버튼의 수의 최솟값을 출력하는 문제로 최단경로값을 구하는 문제였다. 자연스럽게 bfs로 해결할 수 있음을 인지해서 그렇게 풀었다. 

 

 

 

 

 

첫번째로 조심해야할 조건은 만약, U층 위, 또는 D층 아래에 해당하는 층이 없을 때는, 엘리베이터는 움직이지 않는다 이다. 이동할 수 없으면 그자리에서 이동하지 않는다.

 

첫번째 조건은 문제를 읽고 인지하고 있었기 때문에 문제가 되지 않았는데, 두 번째 예외가 있었다. 출발점과 도착점이 같은경우에는 0을 출력해줘야 하는 문제점이다. 

 

그래도 틀린다면 한가지 테스트 케이스를 돌려보세요. 10 5 4 0 1 .......

감이 오시나요?? 저는 이 예외를 인지하지 못해서 엄청 고통받았습니다.

 

 

 

아마 틀리셨다면 위 3개의 조건중에 해답이 있을 거라고 생각합니다. 예외처리 이외의 문제 구현은 어려움이 없으셨을 거라고 생각합니다. 

 

아래는 정답코드입니다.

#include <iostream>
using namespace std;
int f, s, g, u, d;
int que[1000001];
int start=0, ended=0;
int visited[1000001] = { 0 };

void bfs() {

	que[ended++] = s;

	while (start != ended) {

		int current = que[start++];

		if (current + u <= f && !visited[current + u]&& u!=0) {
			visited[current + u] = visited[current] + 1;
			que[ended++] = current + u;
		}
		if (current - d > 0 && !visited[current - d] && d!=0) {
			visited[current - d] = visited[current] + 1;
			que[ended++] = current - d;
		}

	}
}

int main() {
	cin >> f >> s >> g >> u >> d;

	bfs();

	if (!visited[g] && f != s)
		cout << "use the stairs" << endl;
	else
		cout << visited[g] << endl;;
}

 

 

 

 

 

반응형
반응형

문제링크:https://www.acmicpc.net/problem/10026

 

10026번: 적록색약

문제 적록색약은 빨간색과 초록색의 차이를 거의 느끼지 못한다. 따라서, 적록색약인 사람이 보는 그림은 아닌 사람이 보는 그림과는 좀 다를 수 있다. 크기가 N×N인 그리드의 각 칸에 R(빨강), G(초록), B(파랑) 중 하나를 색칠한 그림이 있다. 그림은 몇 개의 구역으로 나뉘어져 있는데, 구역은 같은 색으로 이루어져 있다. 또, 같은 색상이 상하좌우로 인접해 있는 경우에 두 글자는 같은 구역에 속한다. (색상의 차이를 거의 느끼지 못하는 경우도 같은

www.acmicpc.net

 

dfs문제입니다. bfs로도 풀 수 있고 단순히 완전탐색을 하면서 갯수를 세어주면 되는 간단한 문제였습니다. 

방문했는지 여부와 같은색인지를 판별해서 탐색을 했습니다. bfs, dfs 모두 쉽게 구현가능하니까 직접 구현해보시면 좋을 것 같습니다.

 

 

너무쉬워서 설명은 생략하겠습니다. 

 

 

정답코드입니다. 화이팅 :)

#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int n = 0,normal =0,medicine=0;
string arr[100];
bool visited[101][101] = { 0 };
int dex[4] = { 1,-1,0,0 };
int dey[4] = { 0, 0,1,-1 };
void dfs(char color,int x,int y) {

	visited[y][x] = 1;
	
	for (int i = 0; i < 4; i++) {
		int yy = y + dey[i];
		int xx = x + dex[i];
		if (xx >= 0 && xx < n && yy >= 0 && yy< n)
			if (!visited[yy][xx] && arr[yy][xx] == color)
				dfs(color, xx, yy);
	}
}

int main() {
	cin >> n;

	for (int i = 0; i < n; i++)
		cin >> arr[i];

	for(int i=0;i<n;i++)
		for (int j = 0; j < arr[i].size(); j++) 
			if (!visited[i][j]) {
				dfs(arr[i][j], j, i);
				normal++;
			}

	memset(visited, 0, sizeof(visited));

	for (int i = 0; i<n; i++)
		for (int j = 0; j < arr[i].size(); j++) 
			if (arr[i][j] == 'R') arr[i][j] = 'G';

	for (int i = 0; i<n; i++)
		for (int j = 0; j < arr[i].size(); j++)
			if (!visited[i][j]) {
				dfs(arr[i][j], j, i);
				medicine++;
			}

	cout << normal << ' '<< medicine << endl;
	
}
반응형

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

[백준] 2661-좋은수열(C++)  (0) 2020.03.30
[백준] 15666-N과 M (12)(C++)  (0) 2020.03.25
[백준] 2668-숫자고르기(C++)  (0) 2020.03.11
[백준] 2583-영역구하기(C++)  (0) 2020.03.11
[백준] 11403-경로찾기(C++)  (0) 2020.03.07
반응형

문제링크:https://www.acmicpc.net/problem/2589

 

2589번: 보물섬

보물섬 지도를 발견한 후크 선장은 보물을 찾아나섰다. 보물섬 지도는 아래 그림과 같이 직사각형 모양이며 여러 칸으로 나뉘어져 있다. 각 칸은 육지(L)나 바다(W)로 표시되어 있다. 이 지도에서 이동은 상하좌우로 이웃한 육지로만 가능하며, 한 칸 이동하는데 한 시간이 걸린다. 보물은 서로 간에 최단 거리로 이동하는데 있어 가장 긴 시간이 걸리는 육지 두 곳에 나뉘어 묻혀있다. 육지를 나타내는 두 곳 사이를 최단 거리로 이동하려면 같은 곳을 두 번 이상 지

www.acmicpc.net

 

 

최단거리 탐색을 할때는 bfs 알고리즘을 사용합니다.

보물위치의 최단거리를 출력하는 문제였습니다. 

어느지점을 기준으로 출발하느냐에 따라 결과가 달라지기에 조금 생각해야하는 문제였습니다.

 

 

근데 높이,너비가 50까지임으로 저는 모든점에서의 최장거리를 계산해서 문제의 답을 구했습니다.

 

 

한가지 예외처리를 못했던 테스트케이스입니다.

4 4

LLWW

WWWW

WWWW

WWWW

 

이경우 1이 나와야하지만 

간혹 2가 나오는 코드들이 있습니다.

조건문에 (a!= y + de_y[i] || b != x + de_x[i])를 추가해줌으로써 해결했습니다. (출발지점으로 되돌아 오면 안되기 때문에)

 

 

 

기존의 bfs문제들을 풀어보셨다면 쉬운문제였을겁니다.

정답코드입니다. 직접 손으로 작성해보세요 :) 화이팅

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int height, width;

string arr[51];
int visited[51][51];
int que[2501][2];
int started,ended;
int de_x[4] = { 1, 0, 0,-1 };
int de_y[4] = { 0, 1,-1, 0 };
int result = 0;

void bfs(int a, int b) {
	started = 0, ended = 0;
	que[ended][0] = a;
	que[ended][1] = b;
	ended++;

	while (started != ended) {
		int y = que[started][0];
		int x = que[started++][1];
		
		for (int i = 0; i < 4; i++) {
			if ((y + de_y[i])>=0 && (y + de_y[i])<height && (x + de_x[i])>=0 && (x + de_x[i])<width)
				if (arr[y + de_y[i]][x + de_x[i]] == 'L' && !visited[y + de_y[i]][x + de_x[i]] && (a!= y + de_y[i] || b != x + de_x[i]))
				{
					visited[y + de_y[i]][x + de_x[i]] = visited[y][x] + 1;
					que[ended][0] = y + de_y[i];
					que[ended++][1] = x + de_x[i];
					
				}

		}
		
	}

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (arr[i][j] == 'W') continue;
			if (result < visited[i][j] ) result = visited[i][j];
		}
	}


}
int main() {

	cin >> height >> width;
	for (int i = 0; i < height;i++)
		cin >> arr[i];

	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (arr[i][j] == 'W') continue;
			memset(visited, 0, sizeof(visited));
			
			bfs(i,j);


		}
	}

	cout << result << endl;
}
반응형
반응형

문제링크:https://www.acmicpc.net/problem/2644

 

2644번: 촌수계산

사람들은 1, 2, 3, …, n (1≤n≤100)의 연속된 번호로 각각 표시된다. 입력 파일의 첫째 줄에는 전체 사람의 수 n이 주어지고, 둘째 줄에는 촌수를 계산해야 하는 서로 다른 두 사람의 번호가 주어진다. 그리고 셋째 줄에는 부모 자식들 간의 관계의 개수 m이 주어진다. 넷째 줄부터는 부모 자식간의 관계를 나타내는 두 번호 x,y가 각 줄에 나온다. 이때 앞에 나오는 번호 x는 뒤에 나오는 정수 y의 부모 번호를 나타낸다. 각 사람의 부모는 최대

www.acmicpc.net

 

처음에 보자마자 생각난건 union-find 알고리즘이였다. 서로 친척인지 확인을 해주기 위한 방법으로 사용하였다.

그이후에는 몇가지 케이스를 대입보면서 촌수계산을 분명하게 하기위해서는 완전탐색을 해야하는 것을 깨닭았고,

dfs와 bfs중에 고민하였다. 아마 dfs로도 풀이가 가능할 것이다. 탐색에 좀 더 적합한 bfs를 선택했다.

 

 

 

1. search_root() 함수를 통해서 서로 친척인지 확인 

2. 출발점x로부터 y까지 도달하는 과정에서 각 값들을 큐에 저장하며 해당 직계도를 탐색

3. bfs함수 호출이 끝난후 cnt[y]값을 출력 ( 전달받아 오면서 값이 +1씩 증가했으므로 촌수와 동일)

 

bfs에서 !visited[arr[i][1]] 의 조건은 최소의 촌수를 선택해야하기 때문입니다. 

 

 

정답코드입니다. 

 

#include <iostream>
using namespace std;
int n = 0, m = 0, x, y,a,b;
int arr[101][2] = { 0 };
int root_x, root_y;
int cnt[101] = { 0 };
bool visited[101] = { 0 };

void bfs() {

	int que[101] = { 0 };
	int started = 0, ended = 0;

	que[ended++] = x;

	while (started != ended) {
		int val = que[started++];
		visited[val] = 1;

		for (int i = 0; i < m; i++) {
			if (arr[i][0] == val && !visited[arr[i][1]]) {
				
				que[ended++] = arr[i][1];
				cnt[arr[i][1]] = cnt[val] + 1;
			}

			if (arr[i][1] == val && !visited[arr[i][0]]) {
				
				que[ended++] = arr[i][0];
				cnt[arr[i][0]] = cnt[val] + 1;
			}

		}


	}

}


void search_root() {

	root_x = x;
	root_y = y;

	while (1) {
		bool t = false, r = false;
		for (int i = 0; i < m; i++) {
			if (arr[i][1] == root_x) {
				t = true;
				root_x = arr[i][0];

			}
			if (arr[i][1] == root_y) {
				r = true;
				root_y = arr[i][0];
			}
		}
		if (t == false && r == false)
			break;
	}
}


int main() {
	cin >> n;
	cin >> x >> y;
	cin >> m;
	for (int i = 0; i < m; i++)
		cin >> arr[i][0]>>arr[i][1];
	
	search_root();
	if (root_x != root_y) {
		cout << -1 << endl;
		return 0;
	}

	bfs();

	cout << cnt[y] << endl;

}

 

움.. 그런데... 생각해보니 searchroot가 필요가 없죠? 어차피 탐색이 안되면 cnt[y]값을 0일 것이기 때문에 그때만 -1로 출력을 해주면 되기 때문입니다.

 

수정답안 입니다.

 

 

#include <iostream>
using namespace std;
int n = 0, m = 0, x, y,a,b;
int arr[101][2] = { 0 };
int root_x, root_y;
int cnt[101] = { 0 };
bool visited[101] = { 0 };

void bfs() {

	int que[101] = { 0 };
	int started = 0, ended = 0;

	que[ended++] = x;

	while (started != ended) {
		int val = que[started++];
		visited[val] = 1;

		for (int i = 0; i < m; i++) {
			if (arr[i][0] == val && !visited[arr[i][1]]) {
				
				que[ended++] = arr[i][1];
				cnt[arr[i][1]] = cnt[val] + 1;
			}

			if (arr[i][1] == val && !visited[arr[i][0]]) {
				
				que[ended++] = arr[i][0];
				cnt[arr[i][0]] = cnt[val] + 1;
			}

		}


	}

}

int main() {
	cin >> n;
	cin >> x >> y;
	cin >> m;
	for (int i = 0; i < m; i++)
		cin >> arr[i][0]>>arr[i][1];
	
	
	
	bfs();
	if (cnt[y]==0) {
		cout << -1 << endl;
		return 0;
	}

	cout << cnt[y] << endl;
	return 0;
}

 

아이디어자체를 생각하는게 어려운 문제였습니다. 구현난이도는 굉장히 낮구요.

반응형
반응형

문제링크:https://www.acmicpc.net/problem/7569

 

7569번: 토마토

첫 줄에는 상자의 크기를 나타내는 두 정수 M,N과 쌓아올려지는 상자의 수를 나타내는 H가 주어진다. M은 상자의 가로 칸의 수, N은 상자의 세로 칸의 수를 나타낸다. 단, 2 ≤ M ≤ 100, 2 ≤ N ≤ 100, 1 ≤ H ≤ 100 이다. 둘째 줄부터는 가장 밑의 상자부터 가장 위의 상자까지에 저장된 토마토들의 정보가 주어진다. 즉, 둘째 줄부터 N개의 줄에는 하나의 상자에 담긴 토마토의 정보가 주어진다. 각 줄에는 상자 가로줄에 들어있는 토마

www.acmicpc.net

 

BFS알고리즘의 입문용 문제인 토마토 입니다. 기존 토마토와 다른점은 2차원배열을 사용한다는 점입니다.

BFS는 큐를 이용해서 문제를 해결합니다. 

 

 

 

 

입문할때 풀었던 코드라, 난잡하지만 BFS에 대해서 이해하시기는 좋을 것이라고 생각합니다. 

아래는 정답코드입니다.

#include <iostream>
#include<cstring>
#include <queue>
using namespace std;
int arr[102][102][102];
int m = 0, n = 0, cnt = 0, h = 0;
queue<int> x;
queue<int> y;
queue<int> z;

void find(void) {

	for (int k = 1; k <= h; k++)
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {

				if (arr[i][j][k] == 1) { x.push(j), y.push(i), z.push(k); }

			}
		}
}
int search(int sized) {
	if (sized == 0) return 0;
	while (sized--) {
		int x_x = x.front();
		int y_y = y.front();
		int z_z = z.front();
		if (arr[y_y - 1][x_x][z_z] == 0) y.push(y_y - 1), x.push(x_x ),z.push(z_z), arr[y_y - 1][x_x][z_z] =1;
		if (arr[y_y + 1][x_x][z_z] == 0) y.push(y_y + 1), x.push(x_x), z.push(z_z), arr[y_y + 1][x_x][z_z] = 1;
		if (arr[y_y][x_x - 1][z_z] == 0) y.push(y_y), x.push(x_x-1), z.push(z_z), arr[y_y ][x_x-1][z_z] = 1;
		if (arr[y_y][x_x + 1][z_z] == 0) y.push(y_y), x.push(x_x + 1), z.push(z_z), arr[y_y][x_x + 1][z_z] = 1;
		if (arr[y_y][x_x][z_z - 1] == 0) y.push(y_y), x.push(x_x ), z.push(z_z - 1), arr[y_y][x_x][z_z - 1] = 1;
		if (arr[y_y][x_x][z_z + 1] == 0) y.push(y_y), x.push(x_x), z.push(z_z + 1), arr[y_y][x_x][z_z + 1] = 1;
		x.pop(), y.pop(), z.pop();
	}
	return 1;
}
int search2() {
	for (int k = 1; k <= h; k++)
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				{
					if (arr[i][j][k] == 0 && arr[i - 1][j][k] == -1 && arr[i + 1][j][k] == -1 && arr[i][j - 1][k] == -1 && arr[i][j + 1][k] == -1)
						if (arr[i][j][k - 1] == -1 && arr[i][j][k + 1] == -1)
							return 1;

				}
			}
		}
	return 0;
}
int main()
{
	memset(arr, -1, sizeof(int) * 102 * 102 * 102);
	cin >> m >> n >> h;
	for (int k = 1; k <= h; k++) {
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				cin >> arr[i][j][k];
	}


	if (search2() == 1) {
		cout << -1 << '\n';
		return 0;
	}
			
		
	find();

	while (1) {
		int sd = x.size();
		if (search(sd) == 0) break;
		cnt++;
	
		
	}
		
	cout << cnt-1 << '\n';
}
반응형

+ Recent posts