Def) 너비 우선 탐색(BFS, Breadth First Search)
- 현재 정점과 인접한 모든 정점을 방문한 후, 다시 이들 정점과 인접한
모든 정점을 찾아 방문하는 방식.
- 시작 정점으로부터 가까운 정점을 먼저 방문하고,
멀리 떨어진 정점을 나중에 방문.
- 보통 큐를 이용하여 구현
Thm) BFS 구현 With 큐
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101,
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT] = {0,};
size_t g_uVCnt, g_uECnt;
queue_t g_queue;
void BFS(int _nStartV);
int main(void)
{
size_t i, uV1, uV2, uStartV = 1;
scanf("%zu %zu", &g_uVCnt, &g_uECnt);
for (i = 1; i <= g_uECnt; ++i)
{
scanf("%zu %zu", &uV1, &uV2);
g_nAdjMat[uV1][uV2] = TRUE;
g_nAdjMat[uV2][uV1] = TRUE;
}
BFS(uStartV);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nStartV)
{
size_t i;
g_nVisitMat[_nStartV] = TRUE;
enqueue(&g_queue, _nStartV);
printf("%d에서 시작\n", _nStartV);
while (FALSE == isEmpty(&g_queue))
{
int nCurrV = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[nCurrV][i])
{
g_nVisitMat[nCurrV] = TRUE;
enqueue(&g_queue, (int)i);
printf("%d -> %zu\n", nCurrV, i);
}
}
}
}
<hide/>
// TestCase1
4 4
1 2
1 3
2 4
3 4
// Expected
1에서 시작
1에서 2로 이동
1에서 3로 이동
2에서 4로 이동
// TestCase1
6 9
1 2
1 3
2 4
2 5
3 4
3 6
4 5
4 6
5 6
// Expected
1에서 시작
1에서 2로 이동
1에서 3로 이동
2에서 4로 이동
2에서 5로 이동
3에서 6로 이동
Ex) DFS Vs. BFS
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 256
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT] = {0,};
size_t g_uVCnt, g_uECnt;
queue_t g_queue;
void BFS(int _nStartV);
void DFS(int _nCurrV);
int main(void)
{
int i, j;
char uV1, uV2, uStartV;
scanf("%zu %zu", &g_uVCnt, &g_uECnt);
getchar();
for (i = 1; i <= g_uECnt; ++i)
{
scanf("%c %c", &uV1, &uV2);
getchar();
uV1 -= 'A';
uV2 -= 'A';
g_nAdjMat[uV1][uV2] = TRUE;
g_nAdjMat[uV2][uV1] = TRUE;
}
scanf("%c", &uStartV);
uStartV -= 'A';
DFS(uStartV);
printf("\n");
for (i = 1; i <= g_uVCnt; ++i) g_nVisitMat[i] = FALSE;
BFS(uStartV);
/*
printf("%zu %zu", g_uVCnt, g_uECnt);
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
printf("%d ", g_nAdjMat[i][j]);
}
printf("\n");
}
printf("%c", uStartV);
*/
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nStartV)
{
int i;
g_nVisitMat[_nStartV] = TRUE;
enqueue(&g_queue, _nStartV);
printf("%c", _nStartV + 'A');
while (FALSE == isEmpty(&g_queue))
{
int nCurrV = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[nCurrV][i])
{
g_nVisitMat[i] = TRUE;
enqueue(&g_queue, i);
printf("%c", i + 'A');
}
}
}
}
void DFS(int _nCurrV)
{
size_t i;
g_nVisitMat[_nCurrV] = TRUE;
printf("%c", _nCurrV + 'A');
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[_nCurrV][i])
{
DFS(i);
}
}
}
<hide/>
// TestCase1
7 9
A B
B E
A E
B C
B F
C F
C D
D G
G F
A
// Expected
ABCDGFE
ABECFDG
Ex) 바이러스
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT] = {0,};
size_t g_uVCnt, g_uECnt, g_uInfectCnt;
queue_t g_queue;
void BFS(int _nStartV);
int main(void)
{
size_t i, uV1, uV2;
scanf("%zu %zu", &g_uVCnt, &g_uECnt);
for (i = 1; i <= g_uECnt; ++i)
{
scanf("%zu %zu", &uV1, &uV2);
g_nAdjMat[uV1][uV2] = TRUE;
g_nAdjMat[uV2][uV1] = TRUE;
}
BFS(1);
printf("%zu", g_uInfectCnt);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nStartV)
{
int i;
g_nVisitMat[_nStartV] = TRUE;
enqueue(&g_queue, _nStartV);
while (FALSE == isEmpty(&g_queue))
{
int nCurrV = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[nCurrV][i])
{
g_nVisitMat[i] = TRUE;
enqueue(&g_queue, i);
++g_uInfectCnt;
}
}
}
}
<hide/>
// TestCase1
7
6
1 2
2 3
1 5
5 2
5 6
4 7
// Expected
4
Note) 2차원 맵 탐색을 위한 BFS
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101,
DIRECTION = 4
};
typedef struct queue {
int nArray[MAX_COUNT][2];
size_t nCnt;
size_t nFront;
size_t nRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData1, int _nData2);
int isEmpty(queue_t* _pQueue);
int* dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = {0,};
size_t g_uVRowCnt, g_uVColCnt;
queue_t g_queue = {0,};
int g_nDirMat[DIRECTION][2] = { {-1,0}, {1,0}, {0,-1}, {0,1} };
void BFS(int _nStartVRow, int _nStartVCol);
int main(void)
{
size_t i, j, uCnt = 0;
scanf("%zu %zu", &g_uVColCnt, &g_uVRowCnt);
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
scanf("%d", &g_nAdjMat[i][j]);
}
}
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
if (FALSE == g_nVisitMat[i][j] && TRUE == g_nAdjMat[i][j])
{
++uCnt;
BFS(i, j);
}
}
}
printf("%zu", uCnt);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData1, int _nData2)
{
assert(_pQueue->nCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->nRear][0] = _nData1;
_pQueue->nArray[_pQueue->nRear][1] = _nData2;
_pQueue->nRear = (_pQueue->nRear + 1) % MAX_COUNT;
++_pQueue->nCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->nCnt) return TRUE;
return FALSE;
}
int* dequeue(queue_t* _pQueue)
{
int* ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->nFront];
_pQueue->nFront = (_pQueue->nFront + 1) % MAX_COUNT;
--_pQueue->nCnt;
return ret;
}
void BFS(int _nStartVRow, int _nStartVCol)
{
size_t i, j;
g_nVisitMat[_nStartVRow][_nStartVCol] = TRUE;
enqueue(&g_queue, _nStartVRow, _nStartVCol);
printf("(%d, %d) Start.\n", _nStartVRow, _nStartVCol);
while (FALSE == isEmpty(&g_queue))
{
int* nCurrVArr = dequeue(&g_queue);
int nCurrVRow = nCurrVArr[0];
int nCurrVCol = nCurrVArr[1];
for (i = 0; i < DIRECTION; ++i)
{
int nNextVRow = nCurrVRow + g_nDirMat[i][0];
int nNextVCol = nCurrVCol + g_nDirMat[i][1];
if (TRUE == g_nVisitMat[nNextVRow][nNextVCol]) continue;
if (TRUE == g_nAdjMat[nNextVRow][nNextVCol] &&
1 <= nNextVRow && nNextVRow <= g_uVRowCnt &&
1 <= nNextVCol && nNextVCol <= g_uVColCnt)
{
g_nVisitMat[nNextVRow][nNextVCol] = TRUE;
enqueue(&g_queue, nNextVRow, nNextVCol);
printf("(%d, %d) ->(%d, %d)\n", nCurrVRow, nCurrVCol, nNextVRow, nNextVCol);
}
}
}
}
Ex) 마법의 비료
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <math.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101,
DIRECTION = 4
};
typedef struct queue {
int nArray[MAX_COUNT][2];
size_t nCnt;
size_t nFront;
size_t nRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData1, int _nData2);
int isEmpty(queue_t* _pQueue);
int* dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = {0,};
size_t g_uVRowCnt, g_uVColCnt, g_uCnt = 0, g_uArea = 0;
queue_t g_queue = {0,};
int g_nDirMat[DIRECTION][2] = { {-1,0}, {1,0}, {0,-1}, {0,1} };
int g_uAreaArr[MAX_COUNT] = {0,};
void BFS(int _nStartVRow, int _nStartVCol);
int main(void)
{
size_t i, j;
double res = 0;
scanf("%zu %zu", &g_uVColCnt, &g_uVRowCnt);
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
scanf("%d", &g_nAdjMat[i][j]);
}
}
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
if (FALSE == g_nVisitMat[i][j] && TRUE == g_nAdjMat[i][j])
{
++g_uArea;
BFS(i, j);
}
}
}
for (i = 1; i <= g_uArea; ++i)
{
res = res + sqrt((double)g_uAreaArr[i]);
}
printf("%.4lf", res);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData1, int _nData2)
{
assert(_pQueue->nCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->nRear][0] = _nData1;
_pQueue->nArray[_pQueue->nRear][1] = _nData2;
_pQueue->nRear = (_pQueue->nRear + 1) % MAX_COUNT;
++_pQueue->nCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->nCnt) return TRUE;
return FALSE;
}
int* dequeue(queue_t* _pQueue)
{
int* ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->nFront];
_pQueue->nFront = (_pQueue->nFront + 1) % MAX_COUNT;
--_pQueue->nCnt;
return ret;
}
void BFS(int _nStartVRow, int _nStartVCol)
{
size_t i, j;
g_nVisitMat[_nStartVRow][_nStartVCol] = TRUE;
enqueue(&g_queue, _nStartVRow, _nStartVCol);
++g_uAreaArr[g_uArea];
while (FALSE == isEmpty(&g_queue))
{
int* nCurrVArr = dequeue(&g_queue);
int nCurrVRow = nCurrVArr[0];
int nCurrVCol = nCurrVArr[1];
for (i = 0; i < DIRECTION; ++i)
{
int nNextVRow = nCurrVRow + g_nDirMat[i][0];
int nNextVCol = nCurrVCol + g_nDirMat[i][1];
if (TRUE == g_nVisitMat[nNextVRow][nNextVCol]) continue;
if (TRUE == g_nAdjMat[nNextVRow][nNextVCol] &&
1 <= nNextVRow && nNextVRow <= g_uVRowCnt &&
1 <= nNextVCol && nNextVCol <= g_uVColCnt)
{
g_nVisitMat[nNextVRow][nNextVCol] = TRUE;
enqueue(&g_queue, nNextVRow, nNextVCol);
++g_uAreaArr[g_uArea];
}
}
}
}
<hide/>
// TestCase
5 4
1 1 1 1 0
0 0 0 1 1
1 1 0 0 0
0 0 0 0 1
// Expected
4.8637
Ex) 알리바바 미로
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101,
DIRECTION = 4
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = { 0, };
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = { 0, };
size_t g_uVRowCnt, g_uVColCnt, g_uBlockCnt = 0, g_uFinVRow = 1, g_uFinVCol;
int g_nDepth = 0, g_nMinDepth = MAX_COUNT * MAX_COUNT;
int g_nDirMat[DIRECTION][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue_t g_qRow, g_qCol, g_qDep;
int g_nBlockMat[MAX_COUNT][MAX_COUNT] = { 0, };
int flag = 0;
void BFS(int _nStartVRow, int _nStartVCol);
int main(void)
{
size_t i, j, uStartVRow = 5, uStartVCol = 1;
scanf("%zu %zu", &g_uVRowCnt, &g_uVColCnt);
g_uFinVCol = g_uVColCnt;
uStartVRow = g_uVRowCnt;
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
scanf("%1d", &g_nAdjMat[i][j]);
}
}
BFS(uStartVRow, uStartVCol);
/*
printf("\n");
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
printf("%2d ", g_nBlockMat[i][j]);
}
printf("\n");
}
*/
if (0 == flag)
{
printf("-1");
return 0;
}
printf("%d", g_nMinDepth + 1);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nStartVRow, int _nStartVCol)
{
size_t i;
g_nVisitMat[_nStartVRow][_nStartVCol] = TRUE;
enqueue(&g_qRow, _nStartVRow);
enqueue(&g_qCol, _nStartVCol);
enqueue(&g_qDep, g_nDepth);
//printf("Start at (%d, %d).\n", _nStartVRow, _nStartVCol);
while (FALSE == isEmpty(&g_qRow) && FALSE == isEmpty(&g_qCol))
{
int nCurrVRow = dequeue(&g_qRow);
int nCurrVCol = dequeue(&g_qCol);
int nCurrDep = dequeue(&g_qDep);
if (g_uFinVRow == nCurrVRow && g_uFinVCol == nCurrVCol)
{
flag = 1;
if (nCurrDep < g_nMinDepth) g_nMinDepth = nCurrDep;
}
for (i = 0; i < DIRECTION; ++i)
{
int nNextVRow = nCurrVRow + g_nDirMat[i][0];
int nNextVCol = nCurrVCol + g_nDirMat[i][1];
int nNextDep = nCurrDep + 1;
if (TRUE == g_nVisitMat[nNextVRow][nNextVCol]) continue;
if (FALSE == g_nAdjMat[nNextVRow][nNextVCol] &&
1 <= nNextVRow && nNextVRow <= g_uVRowCnt &&
1 <= nNextVCol && nNextVCol <= g_uVColCnt)
{
g_nVisitMat[nNextVRow][nNextVCol] = TRUE;
enqueue(&g_qRow, nNextVRow);
enqueue(&g_qCol, nNextVCol);
enqueue(&g_qDep, nNextDep);
printf("[%d]: (%d, %d) -> (%d, %d)\n", nNextDep, nCurrVRow, nCurrVCol, nNextVRow, nNextVCol);
g_nBlockMat[nNextVRow][nNextVCol] = g_uBlockCnt;
}
}
}
}
<hide/>
10 9
000100110
101010001
010010000
001000000
010010011
001100000
001000101
101000010
010011001
001100100
-1
11 10
0001110000
0010100001
0011100000
0101111010
1000010001
0001000001
1001100111
1101000000
0000100001
0101001001
0001001001
22
Ex) 미로찾기
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101,
DIRECTION = 4
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = {0,};
size_t g_uVRowCnt, g_uVColCnt, g_uVStartRow, g_uVStartCol, g_uVFinishRow, g_uVFinishCol;
int g_nDirMat[DIRECTION][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue_t g_qRow, g_qCol, g_qDep;
int flag = 0;
void BFS(int _nStartRow, int _nStartCol, int _nStartDep);
int main(void)
{
size_t i, j;
scanf("%zu %zu", &g_uVRowCnt, &g_uVColCnt);
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
scanf(" %c", &g_nAdjMat[i][j]);
if ('S' == g_nAdjMat[i][j])
{
g_uVStartRow = i;
g_uVStartCol = j;
}
if ('G' == g_nAdjMat[i][j])
{
g_uVFinishRow = i;
g_uVFinishCol = j;
}
}
}
BFS(g_uVStartRow, g_uVStartCol, 0);
if (0 == flag) printf("-1");
/*
printf("\n%zu %zu\n", g_uVRowCnt, g_uVColCnt);
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
printf("%c", g_nAdjMat[i][j]);
}
printf("\n");
}
*/
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nStartRow, int _nStartCol, int _nStartDep)
{
int i, j;
g_nVisitMat[_nStartRow][_nStartCol] = TRUE;
enqueue(&g_qRow, _nStartRow);
enqueue(&g_qCol , _nStartCol);
enqueue(&g_qDep , _nStartDep);
while (FALSE == isEmpty(&g_qRow) && FALSE == isEmpty(&g_qCol) && FALSE == isEmpty(&g_qDep))
{
int nVCurrRow = dequeue(&g_qRow);
int nVCurrCol = dequeue(&g_qCol);
int nVCurrDep = dequeue(&g_qDep);
for (i = 0; i < DIRECTION; ++i)
{
int nVNextRow = nVCurrRow + g_nDirMat[i][0];
int nVNextCol = nVCurrCol + g_nDirMat[i][1];
int nVNextDep = nVCurrDep + 1;
if (g_uVFinishRow == nVNextRow && g_uVFinishCol == nVNextCol)
{
flag = 1;
printf("%d", nVNextDep);
return;
}
if (TRUE == g_nVisitMat[nVNextRow][nVNextCol]) continue;
if (('.' == g_nAdjMat[nVNextRow][nVNextCol] || 'S' == g_nAdjMat[nVNextRow][nVNextCol]) &&
1 <= nVNextRow && nVNextRow <= g_uVRowCnt &&
1 <= nVNextCol && nVNextCol <= g_uVColCnt)
{
g_nVisitMat[nVNextRow][nVNextCol] = TRUE;
enqueue(&g_qRow, nVNextRow);
enqueue(&g_qCol, nVNextCol);
enqueue(&g_qDep, nVNextDep);
printf("[%d]: (%d, %d) -> (%d, %d)\n", nVNextDep, nVCurrRow, nVCurrCol, nVNextRow, nVNextCol);
}
}
}
}
<hide/>
// TestCase1
5 5
#S###
#...#
#.#.#
#....
###G#
// Expected
6
Ex) 체스 말 이동
- 테스트 케이스는 모두 맞음.
그러나, Segmentation Fault가 뜸.
- Segmentation Fault란, 두 가지 이유로 발생함.
첫째, 허용되지 않은 메모리에 접근(ex. const char*의 수정, nullptr 참조, etc...)
둘째, 허용되지 않은 방법으로 메모리에 접근(나중에 찾아보자.)
- 가장 유력한 부분은, 배열 첨자 연산자에 -2만큼 들어갈 수도 있는 부분.
- 그래서 범위 확인 부분을 우선적으로 검사하게끔,
중첩 if문을 사용함.
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum
{
FALSE = 0,
TRUE = 1,
MAX_COUNT = 10001,
DIRECTION = 8
};
typedef struct queue
{
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = { 0, };
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = { 0, };
size_t g_uVCnt, g_uVStartRow, g_uVStartCol, g_uVFinishRow, g_uVFinishCol;
int g_nDirMat[DIRECTION][2] = { {-1, -2}, {-2, -1}, {-2, 1}, {-1, 2},
{1, -2}, {2, -1}, {2, 1}, {1, 2}
};
queue_t g_qRow, g_qCol, g_qDep;
void BFS(int _nVStartRow, int _nVStartCol, int _nStartDep);
int main(void)
{
size_t i, j;
scanf("%zu %zu %zu %zu %zu", &g_uVCnt, &g_uVStartRow, &g_uVStartCol, &g_uVFinishRow, &g_uVFinishCol);
BFS(g_uVStartRow, g_uVStartCol, 0);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nVStartRow, int _nVStartCol, int _nStartDep)
{
size_t i;
if (g_uVFinishRow == _nVStartRow && g_uVFinishCol == _nVStartCol)
{
printf("0");
return;
}
g_nVisitMat[_nVStartRow][_nVStartCol] = TRUE;
enqueue(&g_qRow, _nVStartRow);
enqueue(&g_qCol, _nVStartCol);
enqueue(&g_qDep, _nStartDep);
while (FALSE == isEmpty(&g_qRow) && FALSE == isEmpty(&g_qCol))
{
int nVCurrRow = dequeue(&g_qRow);
int nVCurrCol = dequeue(&g_qCol);
int nCurrDep = dequeue(&g_qDep);
for (i = 0; i < DIRECTION; ++i)
{
int nVNextRow = nVCurrRow + g_nDirMat[i][0];
int nVNextCol = nVCurrCol + g_nDirMat[i][1];
int nNextDep = nCurrDep + 1;
if (g_uVFinishRow == nVNextRow && g_uVFinishCol == nVNextCol)
{
printf("%d", nNextDep);
return;
}
// if (TRUE == g_nVisitMat[nVNextRow][nVNextCol]) continue;
if (1 <= nVNextRow && nVNextRow <= g_uVCnt &&
1 <= nVNextCol && nVNextCol <= g_uVCnt)
{
if (FALSE == g_nVisitMat[nVNextRow][nVNextCol])
{
g_nVisitMat[nVNextRow][nVNextCol] = TRUE;
enqueue(&g_qRow, nVNextRow);
enqueue(&g_qCol, nVNextCol);
enqueue(&g_qDep, nNextDep);
// printf("[%d]: (%d, %d) -> (%d, %d)\n", nNextDep, nVCurrRow, nVCurrCol, nVNextRow, nVNextCol);
}
}
}
}
}
<hide/>
// TestCase
8
1 1
2 2
// Expected
4
// TestCase
8
0 0
7 0
// Expected
5
// TestCase
100
0 0
30 50
// Expected
28
// TestCase
10
1 1
1 1
// Expected
0
Ex) 토마토
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 1001,
DIRECTION = 4
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = { 0, };
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = { 0, };
size_t g_uVRowCnt, g_uVColCnt;
int g_nDirMat[DIRECTION][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue_t g_qRow, g_qCol, g_qDep;
int g_nDay;
void BFS(void);
int main(void)
{
size_t i, j;
scanf("%zu %zu", &g_uVColCnt, &g_uVRowCnt);
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
scanf("%d", &g_nAdjMat[i][j]);
if (1 == g_nAdjMat[i][j])
{
g_nVisitMat[i][j] = 1;
enqueue(&g_qRow, i);
enqueue(&g_qCol, j);
enqueue(&g_qDep, 1);
}
}
}
BFS();
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
if (0 == g_nVisitMat[i][j] && 0 == g_nAdjMat[i][j])
{
printf("-1");
return 0;
}
}
}
printf("%d", g_nDay - 1);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(void)
{
size_t i, j;
while (FALSE == isEmpty(&g_qRow) && FALSE == isEmpty(&g_qCol))
{
int nVCurrRow = dequeue(&g_qRow);
int nVCurrCol = dequeue(&g_qCol);
int nCurrDep = dequeue(&g_qDep);
for (i = 0; i < DIRECTION; ++i)
{
int nVNextRow = nVCurrRow + g_nDirMat[i][0];
int nVNextCol = nVCurrCol + g_nDirMat[i][1];
int nNextDep = nCurrDep + 1;
if (1 == g_nVisitMat[nVNextRow][nVNextCol])
{
continue;
}
if (0 == g_nAdjMat[nVNextRow][nVNextCol] &&
1 <= nVNextRow && nVNextRow <= g_uVRowCnt &&
1 <= nVNextCol && nVNextCol <= g_uVColCnt)
{
g_nVisitMat[nVNextRow][nVNextCol] = TRUE;
enqueue(&g_qRow, nVNextRow);
enqueue(&g_qCol, nVNextCol);
enqueue(&g_qDep, nNextDep);
}
}
/*
printf("\n\t%d\n", nCurrDep - 1);
for (i = 1; i <= g_uVRowCnt; ++i)
{
for (j = 1; j <= g_uVColCnt; ++j)
{
printf("%d ", g_nVisitMat[i][j]);
}
printf("\n");
}
*/
g_nDay = nCurrDep;
}
}
<hide/>
// TestCase
6 4
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 1
// Expected
8
// TestCase
22 22
1 0 1 -1 0 1 -1 -1 0 1 1 1 0 0 -1 0 0 1 0 1 0 1
1 1 0 1 0 0 0 -1 0 0 1 0 -1 1 0 1 0 -1 1 1 0 -1
0 0 0 0 1 -1 0 1 0 1 0 1 0 1 0 0 -1 1 0 0 0 0
1 0 1 -1 0 1 0 0 0 1 -1 0 1 1 0 0 -1 0 -1 0 1 1
-1 0 0 0 0 -1 1 -1 1 0 0 1 -1 0 1 -1 0 0 0 1 1 0
1 -1 0 1 0 0 1 -1 -1 0 1 -1 1 0 1 1 1 1 1 1 0 1
0 0 1 0 1 1 -1 1 0 -1 -1 0 -1 -1 1 0 1 0 0 0 1 1
-1 -1 0 0 1 1 0 1 0 1 0 0 0 0 0 0 1 -1 1 0 1 0
0 0 -1 0 -1 1 1 0 -1 0 0 -1 -1 -1 0 -1 0 -1 -1 0 0 -1
-1 0 -1 0 1 1 -1 0 0 1 0 1 -1 0 1 1 0 1 1 1 0 0
0 0 1 -1 1 1 1 0 0 1 -1 -1 -1 0 1 0 -1 1 0 0 -1 -1
-1 -1 0 1 -1 0 1 0 0 0 1 1 -1 1 0 0 1 0 -1 -1 1 1
0 -1 0 0 1 0 1 -1 -1 1 -1 0 1 -1 -1 1 1 0 0 1 0 -1
0 0 -1 0 0 1 0 1 0 1 1 0 1 1 1 0 1 0 1 0 1 0
0 1 0 0 0 -1 0 0 0 1 -1 1 0 1 -1 0 1 0 -1 1 -1 0
0 1 0 0 0 1 1 1 -1 -1 0 1 1 0 -1 1 -1 0 0 0 -1 1
1 1 1 0 0 0 1 1 -1 1 0 0 0 0 -1 1 0 0 1 0 0 0
-1 1 0 1 0 0 0 1 -1 1 0 1 -1 -1 0 -1 0 1 0 -1 1 -1
0 0 1 0 -1 1 -1 0 1 0 1 0 0 0 0 -1 -1 0 -1 -1 0 -1
0 1 1 1 0 1 0 0 1 1 -1 1 -1 0 1 1 1 -1 0 -1 0 -1
1 -1 0 -1 -1 0 -1 0 1 -1 0 -1 -1 0 1 0 1 0 0 -1 0 1
-1 0 1 0 0 1 1 0 1 0 0 0 -1 0 0 0 0 0 0 0 0 1
// Expected
4
// TestCase
6 3
1 -1 0 0 0 0
-1 0 -1 0 0 0
0 -1 0 1 0 0
// Expected
-1
Ex) 2색 칠하기
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
enum
{
FALSE = 0,
TRUE = 1,
MAX_COUNT = 1001,
DIRECTION = 2
};
typedef struct queue
{
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = { 0, };
int g_nVisitMat[MAX_COUNT] = { 0, };
size_t g_uVCnt, g_uECnt;
queue_t g_queue;
int g_nFlag = 0;
void BFS(int _nVStart);
int main(void)
{
size_t i, j, uV1, uV2;
scanf("%zu %zu", &g_uVCnt, &g_uECnt);
for (i = 1; i <= g_uECnt; ++i)
{
scanf("%zu %zu", &uV1, &uV2);
g_nAdjMat[uV1 + 1][uV2 + 1] = TRUE;
g_nAdjMat[uV2 + 1][uV1 + 1] = TRUE;
}
BFS(1);
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
if (1 == g_nAdjMat[i][j])
{
if (0 != g_nVisitMat[i] + g_nVisitMat[j])
{
printf("NOT BICOLORABLE");
return 0;
}
}
}
}
printf("BICOLORABLE");
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nVStart)
{
size_t i;
if (0 == g_nVisitMat[_nVStart]) g_nVisitMat[_nVStart] = 1;
enqueue(&g_queue, _nVStart);
while (FALSE == isEmpty(&g_queue))
{
int nVCurr = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (0 == g_nVisitMat[i] && 1 == g_nAdjMat[nVCurr][i])
{
g_nVisitMat[i] = g_nVisitMat[nVCurr] * -1;
enqueue(&g_queue, i);
printf("(%d) -> (%d)\n", nVCurr, i);
}
}
}
}
<hide/>
// TestCase
6
5
0 1
0 2
0 3
0 4
0 5
// Expected
BICOLORABLE
// TestCase
9
10
0 1
0 2
0 3
1 5
2 5
3 4
5 6
5 8
6 7
7 8
// Expected
BICOLORABLE
// TestCase
9 11
0 1
0 2
0 3
1 5
2 5
3 4
4 5
5 6
5 8
6 7
7 8
// Expected
NOT BICOLORABLE
Ex) 꽃길
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 101,
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT] = {0,};
size_t g_uVCnt, g_uECnt;
queue_t g_queue;
void BFS(int _nVStart);
int main(void)
{
size_t i, uV1, uV2, uCnt = 0;
scanf("%zu %zu", &g_uVCnt, &g_uECnt);
for (i = 1; i <= g_uECnt; ++i)
{
scanf("%zu %zu", &uV1, &uV2);
g_nAdjMat[uV1][uV2] = TRUE;
g_nAdjMat[uV2][uV1] = TRUE;
}
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i])
{
BFS(i);
++uCnt;
}
}
printf("%zu", uCnt - 1);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nVStart)
{
size_t i;
g_nVisitMat[_nVStart] = TRUE;
enqueue(&g_queue, _nVStart);
while (FALSE == isEmpty(&g_queue))
{
int nVCurr = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[nVCurr][i])
{
g_nVisitMat[i] = TRUE;
enqueue(&g_queue, i);
printf("%d -> %d\n", nVCurr, i);
}
}
}
}
<hide/>
// TestCase
7
4
1 2
1 3
4 5
6 7
// Expected
2
Ex) 다리 만들기
- [21/12/10]
대륙 색칠 -> 타대륙 BFS 시행. 문제는 방문 처리.
결국 좌상단부터 BFS하기에, 우하단에 위치한 대륙의 끝부분은
이미 방문처리 되어있어서, 최단거리를 못찾게됨..
약 3일정도 도전하였으나, 추후에 BFS를 좀 더 연마하여 도전하기로 결정.
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 1001,
DIRECTION = 4
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = { 0, };
int g_nVisitMat[MAX_COUNT][MAX_COUNT] = { 0, };
size_t g_uVCnt, g_uECnt, g_uCnt = 0;
int g_nDirMat[DIRECTION][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
queue_t g_qRow, g_qCol, g_qDep;
int g_nDepArr[MAX_COUNT] = { 0, }, g_nIdx = 0;
void BFSc(int _nVStartRow, int _nVStartCol);
void BFS(int _nVStartRow, int _nVStartCol, int _nStartCity);
int main(void)
{
size_t i, j, k, l, uV1, uV2;
int min = 2147483647;
scanf("%zu", &g_uVCnt);
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
scanf("%d", &g_nAdjMat[i][j]);
}
}
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
if (FALSE == g_nVisitMat[i][j] && TRUE == g_nAdjMat[i][j])
{
++g_uCnt;
BFSc(i, j); // Adjacency Matrix를 통해, Visit Matrix에 각 대륙 Labeling.
}
}
}
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
g_nAdjMat[i][j] = g_nVisitMat[i][j]; // 각 대륙의 Label을 Adjacency Matrix로 옮김.
g_nVisitMat[i][j] = FALSE; // Visit Matrix는 다시 초기화.
}
}
/*
printf("\n");
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
printf("%d ", g_nAdjMat[i][j]);
}
printf("\n");
}
*/
for (i = 1; i <= g_uVCnt; ++i)
{
for (j = 1; j <= g_uVCnt; ++j)
{
if (FALSE != g_nAdjMat[i][j] && FALSE == g_nVisitMat[i][j])
{
BFS(i, j, g_nAdjMat[i][j]); // 대륙 시작. 타 대륙으로 BFS.
}
}
}
for (i = 0; i < g_nIdx; ++i)
{
if (g_nDepArr[i] < min) min = g_nDepArr[i];
}
printf("%d", min);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFSc(int _nVStartRow, int _nVStartCol)
{
size_t i, j;
g_nVisitMat[_nVStartRow][_nVStartCol] = g_uCnt;
enqueue(&g_qRow, _nVStartRow);
enqueue(&g_qCol, _nVStartCol);
while (FALSE == isEmpty(&g_qRow) && FALSE == isEmpty(&g_qCol))
{
int nVCurrRow = dequeue(&g_qRow);
int nVCurrCol = dequeue(&g_qCol);
for (i = 0; i < DIRECTION; ++i)
{
int nVNextRow = nVCurrRow + g_nDirMat[i][0];
int nVNextCol = nVCurrCol + g_nDirMat[i][1];
if (FALSE != g_nVisitMat[nVNextRow][nVNextCol]) continue;
if (TRUE == g_nAdjMat[nVNextRow][nVNextCol] &&
1 <= nVNextRow && nVNextRow <= g_uVCnt &&
1 <= nVNextCol && nVNextCol <= g_uVCnt)
{
g_nVisitMat[nVNextRow][nVNextCol] = g_uCnt;
enqueue(&g_qRow, nVNextRow);
enqueue(&g_qCol, nVNextCol);
}
}
}
}
void BFS(int _nVStartRow, int _nVStartCol, int _nStartCity)
{
size_t i, j;
int nStartDep = 0;
g_nVisitMat[_nVStartRow][_nVStartCol] = TRUE;
enqueue(&g_qRow, _nVStartRow);
enqueue(&g_qCol, _nVStartCol);
enqueue(&g_qDep, nStartDep);
while (FALSE == isEmpty(&g_qRow) && FALSE == isEmpty(&g_qCol))
{
int nVCurrRow = dequeue(&g_qRow);
int nVCurrCol = dequeue(&g_qCol);
int nCurrDep = dequeue(&g_qDep);
for (i = 0; i < DIRECTION; ++i)
{
int nVNextRow = nVCurrRow + g_nDirMat[i][0];
int nVNextCol = nVCurrCol + g_nDirMat[i][1];
int nNextDep = nCurrDep + 1;
if (1 <= nVNextRow && nVNextRow <= g_uVCnt &&
1 <= nVNextCol && nVNextCol <= g_uVCnt)
{
if (FALSE == g_nVisitMat[nVNextRow][nVNextCol] && 0 == g_nAdjMat[nVNextRow][nVNextCol]) // 만약 바다라면, 더 탐색.
{
g_nVisitMat[nVNextRow][nVNextCol] = TRUE;
enqueue(&g_qRow, nVNextRow);
enqueue(&g_qCol, nVNextCol);
enqueue(&g_qDep, nNextDep);
// printf("[%d]: (%d, %d) -> (%d, %d)\n", nNextDep, nVCurrRow, nVCurrCol, nVNextRow, nVNextCol);
}
else if (_nStartCity != g_nAdjMat[nVNextRow][nVNextCol] && 0 != g_nAdjMat[nVNextRow][nVNextCol])
{ // 바다는 아니고, 출발 대륙과 다르다면 거리 기록.
g_nDepArr[g_nIdx++] = nNextDep - 1;
}
}
}
}
}
<hide/>
// TestCase
10
1 1 1 0 0 0 0 1 1 1
1 1 1 1 0 0 0 0 1 1
1 0 1 1 0 0 0 0 1 1
0 0 1 1 1 0 0 0 0 1
0 0 0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
// Expected
3
// TestCase
36
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
// Expected
4
// TestCase
29
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
// Expected
8
Ex) 소들의 코딩 대회
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 7501,
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nAdjMat[MAX_COUNT][MAX_COUNT] = {0,};
int g_nVisitMat[MAX_COUNT] = {0,};
size_t g_uVCnt = 0, g_uECnt = 0, g_uWinCnt = 0, g_uLoseCnt = 0;
queue_t g_queue;
size_t g_uUpDownCntArray[MAX_COUNT][2];
void BFS_Up(int _nVStart);
void BFS_Down(int _nVStart);
int main(void)
{
size_t i, j, uV1, uV2, cnt = 0;
scanf("%zu %zu", &g_uVCnt, &g_uECnt);
for (i = 1; i <= g_uECnt; ++i)
{
scanf("%zu %zu", &uV1, &uV2);
g_nAdjMat[uV1][uV2] = TRUE;
}
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i])
{
BFS_Up(i);
}
for (j = 1; j <= g_uVCnt; ++j)
{
g_nVisitMat[j] = FALSE;
}
}
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i])
{
BFS_Down(i);
}
for (j = 1; j <= g_uVCnt; ++j)
{
g_nVisitMat[j] = FALSE;
}
}
for (i = 1; i <= g_uVCnt; ++i)
{
if (g_uVCnt - 1 == g_uUpDownCntArray[i][0] + g_uUpDownCntArray[i][1])
{
++cnt;
}
}
printf("%zu", cnt);
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS_Up(int _nVStart)
{
size_t i;
g_nVisitMat[_nVStart] = TRUE;
enqueue(&g_queue, _nVStart);
while (FALSE == isEmpty(&g_queue))
{
int nVCurr = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[i][nVCurr])
{ // nVCurr한테 이기는 소들로 이동.
g_nVisitMat[i] = TRUE;
enqueue(&g_queue, i);
++g_uUpDownCntArray[_nVStart][0];
}
}
}
}
void BFS_Down(int _nVStart)
{
size_t i;
g_nVisitMat[_nVStart] = TRUE;
enqueue(&g_queue, _nVStart);
while (FALSE == isEmpty(&g_queue))
{
int nVCurr = dequeue(&g_queue);
for (i = 1; i <= g_uVCnt; ++i)
{
if (FALSE == g_nVisitMat[i] && TRUE == g_nAdjMat[nVCurr][i])
{ // nVCurr한테 지는 소들로 이동.
g_nVisitMat[i] = TRUE;
enqueue(&g_queue, i);
++g_uUpDownCntArray[_nVStart][1];
}
}
}
}
<hide/>
// TestCase
5 5
4 3
4 2
3 2
1 2
2 5
// Expected
2
Ex) 물통
<hide/>
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
enum {
FALSE = 0,
TRUE = 1,
MAX_COUNT = 201,
};
typedef struct queue {
int nArray[MAX_COUNT];
size_t uCnt;
size_t uFront;
size_t uRear;
} queue_t;
void enqueue(queue_t* _pQueue, int _nData);
int isEmpty(queue_t* _pQueue);
int dequeue(queue_t* _pQueue);
int g_nVisitMat[MAX_COUNT][MAX_COUNT][MAX_COUNT] = {0,};
size_t g_uASize, g_uBSize, g_uCSize, g_uIdx = 0;
queue_t g_qA, g_qC, g_qB;
int g_nStateMat[MAX_COUNT] = {0,};
void BFS(int _nStartA, int _nStartB, int _nStartC);
void move(int _nSrc, int _nDes, int _nKeep, size_t _uDesSize);
int compare(const void* a, const void* b) { return *(int*)a > *(int*)b; }
int main(void)
{
size_t i;
scanf("%zu %zu %zu", &g_uASize, &g_uBSize, &g_uCSize);
BFS(0, 0, (int)g_uCSize);
qsort(g_nStateMat, (int)g_uIdx, sizeof(g_nStateMat[0]), compare);
for (i = 0; i < g_uIdx; ++i)
{
printf("%d ", g_nStateMat[i]);
}
return 0;
}
void enqueue(queue_t* _pQueue, int _nData)
{
assert(_pQueue->uCnt < MAX_COUNT);
_pQueue->nArray[_pQueue->uRear] = _nData;
_pQueue->uRear = (_pQueue->uRear + 1) % MAX_COUNT;
++_pQueue->uCnt;
}
int isEmpty(queue_t* _pQueue)
{
if (0 == _pQueue->uCnt) return TRUE;
return FALSE;
}
int dequeue(queue_t* _pQueue)
{
int ret;
assert(FALSE == isEmpty(_pQueue));
ret = _pQueue->nArray[_pQueue->uFront];
_pQueue->uFront = (_pQueue->uFront + 1) % MAX_COUNT;
--_pQueue->uCnt;
return ret;
}
void BFS(int _nStartA, int _nStartB, int _nStartC)
{
enqueue(&g_qA, _nStartA);
enqueue(&g_qB, _nStartB);
enqueue(&g_qC, _nStartC);
while (FALSE == isEmpty(&g_qA))
{
int nCurrA = dequeue(&g_qA);
int nCurrB = dequeue(&g_qB);
int nCurrC = dequeue(&g_qC);
if (TRUE == g_nVisitMat[nCurrA][nCurrB][nCurrC]) continue;
g_nVisitMat[nCurrA][nCurrB][nCurrC] = TRUE;
// printf("%d %d %d\n", nCurrA, nCurrB, nCurrC);
if (0 == nCurrA)
{
g_nStateMat[g_uIdx++] = nCurrC;
}
// A -> B
if (nCurrA + nCurrB <= g_uBSize)
{
enqueue(&g_qA, 0);
enqueue(&g_qB, nCurrA + nCurrB);
enqueue(&g_qC, nCurrC);
}
else
{
enqueue(&g_qA, nCurrA - (g_uBSize - nCurrB));
enqueue(&g_qB, nCurrB + (g_uBSize - nCurrB));
enqueue(&g_qC, nCurrC);
}
// A -> C
if (nCurrA + nCurrC <= g_uCSize)
{
enqueue(&g_qA, 0);
enqueue(&g_qB, nCurrB);
enqueue(&g_qC, nCurrA + nCurrC);
}
else
{
enqueue(&g_qA, nCurrA - (g_uCSize - nCurrC));
enqueue(&g_qB, nCurrB);
enqueue(&g_qC, nCurrC + (g_uCSize - nCurrC));
}
// B -> A
if (nCurrB + nCurrA <= g_uASize)
{
enqueue(&g_qA, nCurrB + nCurrA);
enqueue(&g_qB, 0);
enqueue(&g_qC, nCurrC);
}
else
{
enqueue(&g_qA, nCurrA + (g_uASize - nCurrA));
enqueue(&g_qB, nCurrB - (g_uASize - nCurrA));
enqueue(&g_qC, nCurrC);
}
// B -> C
if (nCurrB + nCurrC <= g_uCSize)
{
enqueue(&g_qA, nCurrA);
enqueue(&g_qB, 0);
enqueue(&g_qC, nCurrB + nCurrC);
}
else
{
enqueue(&g_qA, nCurrA);
enqueue(&g_qB, nCurrB - (g_uCSize - nCurrC));
enqueue(&g_qC, nCurrC + (g_uCSize - nCurrC));
}
// C -> A
if (nCurrC + nCurrA <= g_uASize)
{
enqueue(&g_qA, nCurrC + nCurrA);
enqueue(&g_qB, nCurrB);
enqueue(&g_qC, 0);
}
else
{
enqueue(&g_qA, nCurrA + (g_uASize - nCurrA));
enqueue(&g_qB, nCurrB);
enqueue(&g_qC, nCurrC - (g_uASize - nCurrA));
}
// C -> B
if (nCurrC + nCurrB <= g_uBSize)
{
enqueue(&g_qA, nCurrA);
enqueue(&g_qB, nCurrC + nCurrB);
enqueue(&g_qC, 0);
}
else
{
enqueue(&g_qA, nCurrA);
enqueue(&g_qB, nCurrB + (g_uBSize - nCurrB));
enqueue(&g_qC, nCurrC - (g_uBSize - nCurrB));
}
}
}
<hide/>
//TestCase
3 6 7
//Expected
1 3 4 6 7
//TestCase
8 9 10
//Expected
1 2 8 9 10
'C > 자료구조와 알고리듬' 카테고리의 다른 글
Chapter 16. Backtracking (0) | 2021.12.12 |
---|---|
Chapter 14. DFS (0) | 2021.11.28 |
Chapter 13. 그래프(Graph) (0) | 2021.11.26 |
Chapter 12. 힙(Heap) (0) | 2021.11.25 |
Chapter 11. 이진 탐색 트리(Binary Search Tree) (0) | 2021.11.21 |
댓글