본문 바로가기

성우리뷰

GPS - dp 갱신

int solution(int n, int m, vector<vector<int>> edge_list, int k, vector<int> gps_log) {
	int answer = 0;
    
	//우선, 인접리스트를 생성한다. 총 n+1개의 것을 생성
    vector<vector<int>> adj(n+1);
    
    for(int i=0; i<m; i++) {
    	int from = edge_list[i][0];
    	int to = edge_list[i][1];
        
        adj[from].push_back(to);
        adf[to].push_back(from);
    }
    
    //dp 생성. 총 k개의 벡터가 존재하며, 각각은 n+1개의 요소로 이뤄짐. 각 요소는 INF값
	//각 로그에서는 n+1개의 노드로 진입이 가능하다. 또한 이는 현재 INF값
    vector<vector<int>> dp(k, vector<int>(n+1, INF));
    dp[0][gps_log[0]] = 0;
    
    //로그의 2번째부터 탐색 시작
    for(int i=1; i<k; i++) {
    	//로그의 i번째 자리가 j일 때, 최소의 고친 횟수를 i-1번째 값부터 가져온다
		//i번째 로그의 자리로 갈 수 있는 방법을 총 n개의 노드로부터 찾아본다.
    	for(int j=1; j<=n; j++) {
        
        	//이동하지 않고, 다음턴에도 그자리에 가만히 있는 경우
        	dp[i][j] = min(dp[i][j], dp[i-1][j]);
            
            //j에 연결된 인접 노드에서 j로 이동한 경우
            for(auto adjnode = adj[j]) {
            	dp[i][j] = min(dp[i-1][adjnode], dp[i][j]);
            }
            
            //dp[i][j] : i번째 j노드로 오면서 최소로 고친 횟수
            
			//로그를 고쳤다면, 횟수 더하기
			//기존의 로그와 j가 같다면, 바뀐게 없음, 안 더함.
			//다르다면, 로그를 고친거이므로 1 더함
            dp[i][j] += (gps_log[i]==j) ? 0 : 1;
        }
    }
    
    //올바른 경로로 수정하는 것이 불가능한 경우
    if(dp[k-1][gps_log[k-1]] >= INF) return -1;
    //끝 경로로 오기까지 고쳐야 하는 로그의 최소횟수
    return dp[k-1][gps_log[k-1]];
}
int main() {
	vector<vector<int>> edge_list = { {1,2},{1, 3},{2, 3},
		{2, 4},{3, 4},{3, 5},{4, 6},{5, 6},{5, 7},{6, 7} };
	vector<int> gps_log = { 1,2,3,3,6,7 };
	int ans = solution(7, 10, edge_list, 6, gps_log);
	cout << ans << "\n";
	return 0;
}