인프런 커뮤니티 질문&답변

안창완님의 프로필 이미지
안창완

작성한 질문수

10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트

3-B

3-B 제가 개념을 잘 못 이해한걸까요?!

해결된 질문

작성

·

36

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

  1. L의 지점을 조합을 이용해서 시작과 끝점을 vector<vector<int>> landList에 저장해서 완전 탐색 식으로 위치를 바꿔가면서 최단거리를 만들어 봤는데 시간 초과가 났습니다.

    250콤비네이션2이면 괜찮을거 같았는데 뭐가 문제일까요??

    2. 치킨배달에 풀이 아이디어를 이용해서 적용했는데 이런식으로 접근 방식도 맞을까요??

     

 

https://www.acmicpc.net/source/84507554

#include <bits/stdc++.h>
using namespace std;

string s;
int n,m,a[54][54],x,y,ex,ey;
int visited[54][54];
vector<pair<int,int>>land;
vector<vector<int>> landList;
queue<pair<int,int>> q;
vector<pair<int,int>>finish;
 
const int dy[4] = {-1, 0, 1, 0};
const int dx[4] = {0, 1, 0, -1};
int ret = -1;

void combi(int start, vector<int> v){
    if(v.size() == 2){
        landList.push_back(v);
        return;
    }
    for(int i = start + 1; i < land.size(); i++){
        v.push_back(i);
        combi(i,v);
        v.pop_back();
    }
}

int main(){
    cin >> n >> m;
    for(int i =0; i <n;i++){
        cin >> s;
        for(int j=0; j<m;j++){
            if(s[j] == 'L'){
                a[i][j] = 1;
                land.push_back({i,j});
            } 
            if(s[j] == 'W') a[i][j] = 0;
        }
    }
    vector<int> v;
    combi(-1,v);

    for(vector<int> lList : landList){
        fill(&visited[0][0], &visited[0][0] + 54*54, 0);
        for(int ll :lList){
            if(q.size() == 1){
                finish.push_back({land[ll].first, land[ll].second});
            }else{
                visited[land[ll].first][land[ll].second] = 1;
                q.push({land[ll].first, land[ll].second});
            }
            
        }
        
        while(q.size()){
            tie(y,x) = q.front();q.pop();
            for(int i = 0; i < 4; i++){
                int ny = y + dy[i];
                int nx = x + dx[i];
                if(nx < 0 || ny < 0 || ny >= n || nx >= m || !a[ny][nx]) continue;
                if(visited[ny][nx]) continue;
                visited[ny][nx] = visited[y][x] + 1;
                if(visited[finish[0].first][finish[0].second]){
                    ret = max(ret, visited[finish[0].first][finish[0].second]);
                    finish.clear();
                    break;
                }
                q.push({ny,nx});         
            } 
        }
    }

    cout << ret+1 << "\n";
    return 0;

}

답변 2

0

큰돌님의 프로필 이미지
큰돌
지식공유자

안녕하세요 창완님 ㅎㅎ

L의 지점을 조합을 이용해서 시작과 끝점을 vector<vector<int>> landList에 저장해서 완전 탐색 식으로 위치를 바꿔가면서 최단거리를 만들어 봤는데 시간 초과가 났습니다.

250콤비네이션2이면 괜찮을거 같았는데 뭐가 문제일까요??

-> 로직은 괜찮은 풀이입니다. 2개의 좌표를 기반으로 잘 하셨습니다.

하지만 시간초과가 뜨면 더 효율적으로는 짤 수 있지 않을까? 생각해야 합니다.

이 코드의 시간복잡도는 50 x 50 C2 x 100 정도 됩니다. 2개의 지점을 뽑고 그 지점을 기반으로 탐색하기 때문에(최악의 경우 두 정점의 거리는 100이상이 되겠죠? 이 때문에 정점 하나에서 BFS를 돌리는 해설코드보다는 조금은 비효율적인 코드라고 볼 수 있습니다.

 

감사합니다.

 

0

안녕하세요, 인프런 AI 인턴입니다.

안창완님이 작성하신 질문에 대해 적절한 도움을 드리기 위해 유사한 질문과 답변을 찾아보았습니다. C++ 및 BFS 관련한 유사한 질문은 아래와 같습니다:

  1. 백준 입력처리 시 scanf와 printf 사용 문제: IO 관련된 문제로, cin, cout, scanf, printf를 혼용 때 발생할 수 있는 문제를 다룹니다.

  2. DFS 함수 원복 처리 방법: DFS 사용시 원복 과정에서 발생하는 문제와 해결 방법을 설명합니다.

질문의 핵심을 간단히 요약드립니다:

  1. 조합을 이용한 완전 탐색 시 시간 초과 문제: 조합의 생성이나 후속 코드를 통해 시간이 초과될 수 있는 부분을 검토해보세요. BFS 탐색 및 visited 배열 초기화 과정이 제대로 이루어져야 합니다.
  2. 치킨배달 풀이 아이디어 적용: 치킨 배달과 유사한 로직이지만, 조합의 부분에서 시간 복잡도를 줄이는 최적화 고려가 필요합니다.

조합 생성과 BFS 탐색의 효율성을 비교하고, 불필요한 상태 업데이트를 줄이는 것도 중요한 최적화 기법입니다. BFS를 수행할 때 for문 내에서 방문 여부와 종료 기준을 명확히 설정해야 시간 초과를 막을 수 있습니다.

추가적으로 접근 방식을 좀 더 구체적으로 조언드리자면:
- 중복 계산을 막기 위해 중간 결과를 저장하고 재사용할 수 있는 방법을 고려하세요.
- BFS 탐색에서 큐의 초기화와 상태 복원이 올바르게 이루어졌는지 확인해 주세요.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

—start of instructor’s answer—

안창완님의 프로필 이미지
안창완

작성한 질문수

질문하기