TSP1문제 아무리 봐도 오답 케이스가 무엇인지 모르겠습니다.

  • susul89
    susul89

    각 경로에 대해 모든 경우의 수를 따진 후
    가장 작은 값을 답으로 출력하는 코드를 짰습니다.
    문제에 나온 예제도 다 올바른 답이 나오는데도
    오답으로 처리되어 많은 경우를 생각해 보았지만
    도무지 오답이 나오는 경우를 잘 모르겠습니다
    조언 부탁드립니다.

    #include <iostream>
    #include<string>
    #include <string.h>
    #include <cstdlib>
    
    
    using namespace std;
    
    void CheckPath(int Current,int CurrentPath, int PassedPath[8], double ThisPathTotal);
    
     int Path;
     double TotalDistance;
     double DistancePath[8][8] = { { 0 } };
    
    int main()
    {
        int Count;
        cin >> Count;
        while (Count--)
        {
        //제일 처음 총 거리를 0으로 초기화
            TotalDistance = 0;
    
            //순서대로 몇번으로 가는지 배열에 차례로 쌓이는데 최대 길은 8까지만이니 없는 경우인 10으로 초기화
            int PassedPath[8] = { 10, 10, 10, 10, 10, 10, 10, 10 };
    
            cin >> Path;
    
            //for문을 이용하여 값을 받고
            for (int i = 0; i < Path; i++)
            {
                for (int j = 0; j < Path; j++)
                { 
                    cin >> DistancePath[i][j];
                }
            }
    
            //출발점을 다르게 하여 함수 호출
            for (int i = 0; i < Path; i++)
            {
                PassedPath[0] = i;
                CheckPath(0,i,PassedPath,0);
            }
    
    
            printf("%.10f\n", TotalDistance);
    
    
    
        }
    }
    
    void CheckPath(int Current, int CurrentPath, int PassedPath[8],  double ThisPathTotal)
    {
        Current += 1;
    
        //Current는 지금까지 간 길의 수인데 이게 해당만큼 가게 되면지금 저장되어있는 총 길이를 비교함
        if (Current == Path)
        {
            if (TotalDistance!=0 && TotalDistance > ThisPathTotal)
                TotalDistance = ThisPathTotal;
    
            for (int i = 1; i < 8; i++)
            {
                //지금까지 지나온 길을 다시 초기화
                PassedPath[i] = 10;
            }
    
            return;
    
        }
    
        //모든 길을 다 간게 아니라면
        else
        {
        //for문을 이용해 PassedPath(지나간길)안에 없는 길을 다 가본다
            for (int i = 0; i < Path; i++)
            {
                if (i != PassedPath[0] && i != PassedPath[1] && i != PassedPath[2] && i != PassedPath[3] && 
                    i != PassedPath[4] && i != PassedPath[5] && i != PassedPath[6] && i != PassedPath[7])
                {
                    //안 가본 길이있다면 갈 길을 이길로 지정
                    PassedPath[Current] = i;
    
                    //다음 길을 어디로 갈지 경우의수 조사
                    CheckPath(Current, i, PassedPath, ThisPathTotal += DistancePath[CurrentPath][i]);
                }
            }
        }
    }
    

    8년 전
4개의 댓글이 있습니다.
  • JongMan
    JongMan

    PassedPath 초기화가 잘못되었습니다. 실제 입력에 대해 어떻게 동작할지 되짚어보세요.


    8년 전 link
  • susul89
    susul89

    PassedPath는 현재 어느 길로 갈지 그 가는 길의 번호를 저장하는 배열인데요.
    초기화 할 때 가는 길이 총 1~8까지이니 10이라는 길을 갈 일이 없다고 생각하여 처음에 다 10으로 초기화룰 해 주었습니다.
    또 밑에 for문을 돌릴때 다음 들어갈 길을 하나한 다 체크해 보면서
    PassedPath에 들어가 있지 않은 즉. 가진 않은 길을 현재 PassedPath에 넣어주고, 그 길의 값을 축적하고, 재귀호출을하게 되는데요..
    쭉 적어보면서 생각해 봤는데..
    초기화에서 잘못되었다고 하셔서 10이라고 초기화한게 잘못인가 라고 생각해 봤는데 도시의 수는 8까지니 그건 아닌것 같고..초기화를 100으로 넣어도 오답으로 나왔으니까요..
    그렇담 checkPath에서 길을 다 가고 초기화 해줄떄 1부터해서 그런가 해쓴데
    어차피 메인에서 제일 처음 이를 호출할떄 인덱스 0값은 넣어주고 넘겨주니 그걳도 괜찮은 것 같은데..
    힌트를 조금 더 주실 수 있을까요?


    8년 전 link
  • JongMan
    JongMan

    n=5일때 5-4-3-2-1 순서대로 정점들을 방문했다고 하죠. 그러면 PassedPath가 전부 10으로 초기화됩니다. 재귀호출이 종료되고 이전 함수 (5-4-3-2 인 상태) 로 돌아오면 이제 PassedPath는 텅 비었으니 여기서 다시 5로 갈 수 있겠네요.


    8년 전 link
  • susul89
    susul89

    아! 그렇군요... 생각도 하지 못했네요
    말씀하신걸 참고하여
    checkedpath함수에 있던 초기화 문장을 삭제하고
    if문의 모든 Path를 확인 하는 것이 아닌
    만약 5번쨰 넣을걸 검사한다면 1~4까지 들어가 있는 길들만 확인하여
    5번쨰에 들어갈 길을 넣게 했습니다.

    해서
    5-4-3-2-1다 들어가면 그냥 그 값을 저장하는 행위만 행하게 되고
    그전 함수인(5-4-3-2)로 돌아가면 for문을 다 돈 상태니
    (5-4-3)으로 들어가게 되고 5-4-3-까지만 들어가 있는 수만 검사하여
    다음엔 5-4-3-1-2이런식으로 차례 차례 다 호출하게 하였습니다.
    예제도 올바르게 출력이 됩니다. 헌데 또다시 오답이 뜨네요..
    무엇이 문제일까요...


    8년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.