최대 동전을 움직일 수 있는 수를 구하는 문제 (무한번이면 -1)
dfs를 이용한 탐색으로 해결
void dfs(int x,int y,int cnt)
char map[51][51];
int visit[51][51];
int dp[51][51];
if(visit[x][y]==1){
Max = 999999;
return;
}
visit[x][y] = 1;
for(int i=0;i<4;i++){
int xx = x + _x[i]*(map[x][y]-'0');
int yy = y + _y[i]*(map[x][y]-'0');
if(xx>=0&&yy>=0&&xx<m&&yy<n&&map[xx][yy]!='H'){ // 이동 가능할때
dfs(xx,yy,cnt+1);
}else{ // 빠질때
if(Max == 999999)
return;
if(Max<cnt+1){
Max = cnt+1;
}
}
}
int xx = x + _x[i]*(map[x][y]-'0');
int yy = y + _y[i]*(map[x][y]-'0');
map[xx][yy] : 미래 이동할 위치
이동 가능하다면 : dfs(xx,yy,cnt+1) 로 이동한 이후의 Max 재귀적으로 구함
이동 불가능하다면 : 종료하는 것이 아니라 구멍에 빠지는 이동횟수도 계산에 포함하므로 cnt+1로 이동횟수를 가정한 다음 Max를 이에 맞게 변경
visit[x][y] = 0;
visit는 한 경로에 대해서 무한루프를 도는 건지 확인하는 용도
첫번째 중복 방문 그림은 무한루프를 도는것이 맞지만
두번째 중복 방문은 무한루프를 도는 것이 아니다
따라서 visit는 한 경로에 대해서만 표기해야함..
위의 경우만 고려하면 시간초과가 나게 된다...
dp까지 이용해서 한번 더 계산을 걸러주어야 함
if(dp[x][y]>=cnt){
return;
}
dp[x][y]=cnt;
dp 배열에다 방문시 제일 큰 cnt를 저장해둔다
-> 다른 재귀 반복때 같은 칸 방문시 dp에 저장된 수보다 cnt가 작다면 굳이 뒤를 계산할 필요가 없게 된다 (어짜피 dp가 큰 방문때의 cnt보다 작은 값이 나오게 됨)
#include <stdio.h>
#include <string.h>
char map[51][51];
int visit[51][51];
int dp[51][51];
int Max = 0;
int _x[4] = {0,0,1,-1};
int _y[4] = {1,-1, 0,0};
int m,n;
void dfs(int x,int y,int cnt){
if(visit[x][y]==1){
Max = 999999;
return;
}
if(dp[x][y]>=cnt){
return;
}
dp[x][y]=cnt;
visit[x][y] = 1;
for(int i=0;i<4;i++){
int xx = x + _x[i]*(map[x][y]-'0');
int yy = y + _y[i]*(map[x][y]-'0');
if(xx>=0&&yy>=0&&xx<m&&yy<n&&map[xx][yy]!='H'){ // 이동 가능할때
dfs(xx,yy,cnt+1);
}else{ // 빠질때
if(Max == 999999)
return;
if(Max<cnt+1){
Max = cnt+1;
}
}
}
visit[x][y]=0;
}
int main(){
memset(dp, -1, sizeof(dp));
scanf("%d %d",&m,&n);
for(int i=0;i<m;i++){
scanf("%s",&map[i]);
}
dfs(0,0,0);
if(Max == 999999)
printf("-1");
else
printf("%d",Max);
}