ALLERGY 문제 질문입니다.

  • freestar
    freestar

    ALLERGY 문제를 푸는 중입니다.

    테스트 케이스 다 맞고
    제가 추가로 10개는 넘게 만들어서 테스트 한 것도 모두 맞았는데
    오답이라고 자꾸 결과가 나옵니다.

    다른 라이브러리를 안쓰려고 하다보니,
    그리고 깔끔하게 짜는 능력이 모자라서
    코드가 길고 지저분해서 봐주실 수 있을지 모르겠습니다만

    혹시 가능하시다면 조언 부탁드립니다.

    우선 순위 큐를 이용해서
    먹을 수 있는 음식 수가 가장 적은 사람부터 생각했습니다.
    그 사람이 먹을 수 있는 음식 중에
    가장 많은 사람이 먹을 수 있는 음식을 택하는 식입니다.

    #include<stdio.h>
    
    
    typedef struct Person{
    
        char name[11];
        int foods[51];
        int num_foods = 0;
        bool avail = false;
    
    }PERSON;
    
    PERSON P[100];
    
    
    
    int end = 0;
    
    void swap(PERSON* a, PERSON* b)
    {
        PERSON tmp;
        tmp = *a;
        *a = *b;
        *b = tmp;
    }
    void add(PERSON n)
    {
        end++;
        P[end] = n;
        int idx = end;
        int parent = idx / 2;
    
        while (idx>1)
        {
            if (P[parent].num_foods > P[idx].num_foods)
            {
                swap(&P[parent], &P[idx]);
                idx = parent;
                parent = idx / 2;
            }
            else break;
        }
    
    }
    
    PERSON pop()
    {
        PERSON ret = P[1];
        P[1] = P[end];
        end--;
        int idx = 1;
        int child = 2;
        while (child <= end)
        {
            if (P[child].num_foods > P[child + 1].num_foods) child++;
            if (P[idx].num_foods > P[child].num_foods)
            {
                swap(&P[idx], &P[child]);
                idx = child;
                child = child * 2;
            }
            else break;
        }
    
    
        return ret;
    }
    int strcmp(char *a, char *b)
    {
        int flag = 0;
        while (*a)
        {
            if (*(a++) != *(b++)) return -1;
        }
        if (*a != *b) return -1;
        return 1;
    }
    
    void strcpy(char *a, char *b)
    {
        while (*b)
        {
            *(a++) = *(b++);
        }
        *a = '\0';
    }
    int main()
    {
    
        int T;
        int n, m;
    
        char friends[100][11];
        char foods[100][100][11];
        int num_foods[100]; // i번째 음식을 먹을 수 있는 사람 수
        int FOODS[100] = { 0, }; // i번째 음식이 선택 되었는가(1) 안되었는가(0)
        int total = 0; // 먹을 음식이 있는 사람의 수
        int total_foods = 0; // 선택한 음식의 수
        PERSON p[100];
    
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d %d", &n, &m);
            for (int i = 1; i <= n; i++)
            {
                scanf("%s", &friends[i]);
                strcpy(p[i].name, friends[i]);
                p[i].avail = false;
                p[i].num_foods = 0;
            }
    
            for (int i = 1; i <= m; i++)
            {
                scanf("%d", &num_foods[i]);
                for (int j = 1; j <= num_foods[i]; j++)
                {
                    scanf("%s", &foods[i][j]);
                    for (int k = 1; k <= n; k++)
                    {
                        if (strcmp(p[k].name, foods[i][j]) == 1)
                            p[k].foods[++p[k].num_foods] = i;
                    }
                }
                FOODS[i] = 0;
    
            }
    
            // 우선 순위 큐에 넣음
            for (int i = 1; i <= n; i++)
                add(p[i]);
    
    
            PERSON select;
    
            for (int i = 1; i <= n; i++)
            {
                select = pop(); //먹을 수 있는 음식 수가 가장 적은 사람 
    
                if (select.avail == false)
                {
                    select.avail = true;
                    total++; //먹을 음식이 있는 사람 수
                }
                else continue;
    
                //select food ->  select가 먹는 음식들 중 사람들이 많이 먹을 수 있는 음식 선택하기
                int max = 0; int idx = -1;
                for (int j = 1; j <= select.num_foods; j++)
                {
                    if (FOODS[select.foods[j]] == 0)// 아직 선택이 안된 음식
                    {
                        //select.food[j] -> select가 먹을 수 있는 음식들 중 j번째 음식을 먹는 사람 수
                        if (max < num_foods[select.foods[j]]) 
                        {
                            max = num_foods[select.foods[j]];
                            idx = select.foods[j];
                        }
                    }
                }
    
                FOODS[idx] = 1; // idx 음식은 선택됨
                total_foods++; // 선택된 음식 수
    
                //select가 먹을 음식(idx)을 선택했으니까, 얘가 먹는 음식들, 그 음식들을 먹는 사람 수 1씩 감소. 
                for (int j = 1; j <= select.num_foods; j++)
                {
                    num_foods[select.foods[j]]--;
                }
    
                //위 음식을 택함으로 자동적으로 먹을 음식이 생긴 사람들.  idx 번째 음식을 먹는 사람들.
                for (int j = 1; j <= end; j++)
                {
                    if (P[j].avail == true) continue;//이미 선택된 사람들 넘어가고
    
                    for (int k = 1; k <= P[j].num_foods; k++) // P[j]가 먹는 음식들
                    {
                        if (P[j].foods[k] == idx) // 그 중에 아까 선택한 음식이 있다
                        {
                            P[j].avail = true; // 그러면 P[j]는 선택
                            total++;            //먹을 음식이 있는 사람 수 증가
    
                            //음식을 먹을 수 있는 사람 수 조정 - 선택된 사람들 빼기
                            for (int l = 1; l <= P[j].num_foods; l++) // P[j]를 선택하면, P[j]가 먹는 음식들 걔네들을 먹는 사람 수 감소. P[j]를 아예 배제하기 위해
                            {
                                num_foods[P[j].foods[l]]--;
                            }
                            break;
                        }
                    }
                }
    
                if (total == n) break;
            }
            printf("%d\n", total_foods);
    
            //initializing
            total = 0;
            total_foods = 0;
            end = 0;
        }
        return 0;
    }
    

    8년 전
1개의 댓글이 있습니다.
  • freestar
    freestar

    오류를 찾았습니다.


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