728x90

문제 링크 : www.acmicpc.net/problem/7562

 

 

7562번: 나이트의 이동

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수

www.acmicpc.net

 

시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 20314 9583 7226 46.490%

 

문제

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수 있을까?

입력

입력의 첫째 줄에는 테스트 케이스의 개수가 주어진다.

각 테스트 케이스는 세 줄로 이루어져 있다. 첫째 줄에는 체스판의 한 변의 길이 l(4 ≤ l ≤ 300)이 주어진다. 체스판의 크기는 l × l이다. 체스판의 각 칸은 두 수의 쌍 {0, ..., l-1} × {0, ..., l-1}로 나타낼 수 있다. 둘째 줄과 셋째 줄에는 나이트가 현재 있는 칸, 나이트가 이동하려고 하는 칸이 주어진다.

출력

각 테스트 케이스마다 나이트가 최소 몇 번만에 이동할 수 있는지 출력한다.

 

 

 

 

접근 방법 1

시작지점부터 BFS를 돌면서 체스가 이동할 수 있는 8곳을 방문한다. 시작지점부터 해당 지점까지의 거리를 이차원 배열인 fromStart[][]에 저장한다. 1389번과 같은 방식으로 접근했는데 메모리 초과가 떴다. 

 

 

 

#include <iostream>
#include <queue>
#include <utility>
using namespace std;
//11부터 시계 반대방향
int dr[8] = {-2,-1,1,2,2,1,-1,-2};
int dc[8] = {-1,-2,-2,-1,1,2,2,1};
queue<pair<int,int>> que;
int I, cur1, cur2, next1, next2, cnt;
int fromStart[300][300];
void settingMap(){
for(int i = 0; i<I; i++){
for(int j = 0; j<I; j++){ fromStart[i][j] = 0;}
}
}
void printMap(){
for(int i = 0; i<I; i++){
for(int j = 0; j<I; j++){
cout << fromStart[i][j] << " ";
} cout << endl;
}
cout << endl;
}
int BFS(){
int res = 0;
while(!que.empty()){
// printMap();
int r = que.front().first;
int c = que.front().second;
que.pop();
if(r==next1 && c==next2){ //도착지점이면 그 지점까지의 거리 리턴
return fromStart[r][c];
}
for(int i = 0; i<8; i++){
int nr = r + dr[i];
int nc = c + dc[i];
if(nr>=I || nr<0 || nc>=I || nc<0){ //범위 벗어나면 패스
continue;
}
//옮길 곳이 범위 안에 들어옴
que.push(make_pair(nr, nc));
//1. 다음 방문할 곳이 0이면 -> 방문 안한 곳이니까 +1
if(fromStart[nr][nc]==0){
fromStart[nr][nc] = fromStart[r][c] + 1;
}
//2. 다음 방문할 곳이 0이 아니면 -> 기존 값이랑 비교해서 더 작은것으로 적음
else{
if(fromStart[nr][nc] > fromStart[r][c] + 1){
fromStart[nr][nc] = fromStart[r][c] + 1;
}
}
}
}
return -1;
}
int main(){
int TC;
cin >> TC;
for(int t = 0; t<TC; t++){
settingMap();
cin >> I >> cur1 >> cur2 >> next1 >> next2;
que.push(make_pair(cur1,cur2));
cout << BFS() << endl;
que = queue<pair<int,int>>();
}
return 0;
}

 

 

 매 테스트 케이스마다 [que = queue<pair<int,int>>();] 로 큐를 초기화했는데도 메모리 초과 문제가 해결되지 않았다.

 

 

 

접근 방법 2

위에서는 말을 이동할 때

기존의 방문할 칸까지의 거리(fromStart[nr][nc]) 가 현재 칸(fromStart[r][c])까지의 거리 +1 보다 클때 더 작은 값으로 교체해주었다. 그러나 그럴 필요가 없었다. 어짜피 BFS로 돌리니까 해당 칸을 방문한 즉시 그 칸까지의 거리가 최소가 되기 때문이다.

 

이번에는fromStart[][]도 매 테스트 케이스마다 초기화하는 코드도 추가했다.

#include <iostream>
#include <queue>
#include <utility>
using namespace std;
//11부터 시계 반대방향
int dr[8] = {-2,-1,1,2,2,1,-1,-2};
int dc[8] = {-1,-2,-2,-1,1,2,2,1};
queue<pair<int,int>> que;
int I, cur1, cur2, next1, next2, cnt;
int fromStart[300][300];
void settingMap(){
for(int i = 0; i<I; i++){
for(int j = 0; j<I; j++){ fromStart[i][j] = 0;}
}
}
int BFS(){
int res = 0;
while(!que.empty()){
int r = que.front().first;
int c = que.front().second;
que.pop();
if(r==next1 && c==next2){ //도착지점이면 그 지점까지의 거리 리턴
res = fromStart[r][c];
break;
}
for(int i = 0; i<8; i++){
int nr = r + dr[i];
int nc = c + dc[i];
if(nr>=I || nr<0 || nc>=I || nc<0){ //범위 벗어나면 패스
continue;
}
if(fromStart[nr][nc]==0){ //옮길 곳이 범위 안에 들어오고 방문 안한 곳이면
fromStart[nr][nc] = fromStart[r][c] + 1;
que.push(make_pair(nr, nc));
}
}
}
return res;
}
int main(){
int TC;
cin >> TC;
for(int t = 0; t<TC; t++){
settingMap();
cin >> I >> cur1 >> cur2 >> next1 >> next2;
que.push(make_pair(cur1,cur2));
cout << BFS() << endl;
que = queue<pair<int,int>>();
}
return 0;
}

 

 

728x90

+ Recent posts