테스트 케이스 다 맞고
제가 추가로 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;
}
freestar
[[problem:ALLERGY]] 문제를 푸는 중입니다.
테스트 케이스 다 맞고
제가 추가로 10개는 넘게 만들어서 테스트 한 것도 모두 맞았는데
오답이라고 자꾸 결과가 나옵니다.
다른 라이브러리를 안쓰려고 하다보니,
그리고 깔끔하게 짜는 능력이 모자라서
코드가 길고 지저분해서 봐주실 수 있을지 모르겠습니다만
혹시 가능하시다면 조언 부탁드립니다.
우선 순위 큐를 이용해서
먹을 수 있는 음식 수가 가장 적은 사람부터 생각했습니다.
그 사람이 먹을 수 있는 음식 중에
가장 많은 사람이 먹을 수 있는 음식을 택하는 식입니다.
11년 전