문제
https://www.acmicpc.net/problem/1103
1103번: 게임
줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. 이 값은 모두 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 보드의 상태가 주어진다. 쓰여 있는 숫자는 1부터 9까지의 자연수 또는
www.acmicpc.net
게임을 진행하면서 움직일 수 있는 동전의 최대 횟수를 구하는 문제였다.
문제 풀이
많은 시행착오가 있었고, 결국 다른 블로그를 참고해서 해결했다.
처음에는 단순히 백트래킹을 이용했는데, 6%에서 시간 초과가 나타났다. 이를 해결하기 위해서 좌표와 횟수, 방향 정보를 우선순위 큐에 넣어 bfs를 돌렸는데 해결되지 않는 경우가 있었다. 그리고 map의 각 칸에 set을 만들어 이전에 방문한 적이 있는지를 판단하도록 했는데 1%에서 틀렸다고 했다. dp를 사용해야 할 것 같긴 한데 어떻게 사용해야 할지 모르겠어서 다른 블로그를 참고했는데 생각보다 너무 간단해서 놀랐다.
dfs에 인자로 넘겨주던 cnt를 dp로 관리하고, 중간에 갱신되지 않을 때에는 dfs를 돌리지 않게 해 탐색 횟수를 줄여서 해결 가능했다. 이번 문제는 혼자서 풀지 못했지만 앞으로 이런 유형의 문제는 풀 수 있을 것 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <string>
using namespace std;
typedef struct info {
int x;
int y;
int cnt;
int dir;
}info;
int N, M;
vector<vector<int>> map;
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };
bool isInf = false;
vector<vector<bool>> visit;
vector<vector<int>> dp;
int maxCnt = 0;
bool isInside(int x, int y) {
if (x >= 0 && x < N && y >= 0 && y < M) return true;
return false;
}
void dfs(int x, int y) {
if (isInf) return;
//printf("%d %d cnt: %d\n", x, y, cnt);
maxCnt = max(maxCnt, dp[x][y]);
for (int i = 0; i < 4; i++) {
int nx = x + dx[i] * map[x][y];
int ny = y + dy[i] * map[x][y];
if (isInside(nx, ny) && map[nx][ny] != -1) {
//현재 칸을 이전에 방문했는지 체크
if (!visit[nx][ny]) { //방문 전
if (dp[nx][ny] >= dp[x][y] + 1) continue; //갱신 안되는 상황 -> 탐색 x
visit[nx][ny] = true;
dp[nx][ny] = dp[x][y]+1;
dfs(nx, ny);
visit[nx][ny] = false;
}
else {
isInf = true;
return;
}
}
}
}
int main() {
scanf("%d %d", &N, &M);
map = vector<vector<int>>(N, vector<int>(M));
dp = vector<vector<int>>(N, vector<int>(M, -1));
visit = vector<vector<bool>>(N, vector<bool>(M, false));
for (int i = 0; i < N; i++) {
string str;
cin >> str;
for (int j = 0; j < M; j++) {
if (str[j] >= '0' && str[j] <= '9') map[i][j] = str[j] - '0';
else map[i][j] = -1;
}
}
dp[0][0] = 1;
dfs(0, 0);
if (isInf) printf("-1");
else printf("%d", maxCnt);
return 0;
}
/*
*/
문제
https://www.acmicpc.net/problem/1103
1103번: 게임
줄에 보드의 세로 크기 N과 가로 크기 M이 주어진다. 이 값은 모두 50보다 작거나 같은 자연수이다. 둘째 줄부터 N개의 줄에 보드의 상태가 주어진다. 쓰여 있는 숫자는 1부터 9까지의 자연수 또는
www.acmicpc.net
게임을 진행하면서 움직일 수 있는 동전의 최대 횟수를 구하는 문제였다.
문제 풀이
많은 시행착오가 있었고, 결국 다른 블로그를 참고해서 해결했다.
처음에는 단순히 백트래킹을 이용했는데, 6%에서 시간 초과가 나타났다. 이를 해결하기 위해서 좌표와 횟수, 방향 정보를 우선순위 큐에 넣어 bfs를 돌렸는데 해결되지 않는 경우가 있었다. 그리고 map의 각 칸에 set을 만들어 이전에 방문한 적이 있는지를 판단하도록 했는데 1%에서 틀렸다고 했다. dp를 사용해야 할 것 같긴 한데 어떻게 사용해야 할지 모르겠어서 다른 블로그를 참고했는데 생각보다 너무 간단해서 놀랐다.
dfs에 인자로 넘겨주던 cnt를 dp로 관리하고, 중간에 갱신되지 않을 때에는 dfs를 돌리지 않게 해 탐색 횟수를 줄여서 해결 가능했다. 이번 문제는 혼자서 풀지 못했지만 앞으로 이런 유형의 문제는 풀 수 있을 것 같다.
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <string> using namespace std; typedef struct info { int x; int y; int cnt; int dir; }info; int N, M; vector<vector<int>> map; int dx[4] = { -1,1,0,0 }; int dy[4] = { 0,0,-1,1 }; bool isInf = false; vector<vector<bool>> visit; vector<vector<int>> dp; int maxCnt = 0; bool isInside(int x, int y) { if (x >= 0 && x < N && y >= 0 && y < M) return true; return false; } void dfs(int x, int y) { if (isInf) return; //printf("%d %d cnt: %d\n", x, y, cnt); maxCnt = max(maxCnt, dp[x][y]); for (int i = 0; i < 4; i++) { int nx = x + dx[i] * map[x][y]; int ny = y + dy[i] * map[x][y]; if (isInside(nx, ny) && map[nx][ny] != -1) { //현재 칸을 이전에 방문했는지 체크 if (!visit[nx][ny]) { //방문 전 if (dp[nx][ny] >= dp[x][y] + 1) continue; //갱신 안되는 상황 -> 탐색 x visit[nx][ny] = true; dp[nx][ny] = dp[x][y]+1; dfs(nx, ny); visit[nx][ny] = false; } else { isInf = true; return; } } } } int main() { scanf("%d %d", &N, &M); map = vector<vector<int>>(N, vector<int>(M)); dp = vector<vector<int>>(N, vector<int>(M, -1)); visit = vector<vector<bool>>(N, vector<bool>(M, false)); for (int i = 0; i < N; i++) { string str; cin >> str; for (int j = 0; j < M; j++) { if (str[j] >= '0' && str[j] <= '9') map[i][j] = str[j] - '0'; else map[i][j] = -1; } } dp[0][0] = 1; dfs(0, 0); if (isInf) printf("-1"); else printf("%d", maxCnt); return 0; } /* */