Az alábbi letöltési lehetőségek közül választhatsz: (
segítség)
Típus: text/plain
Tartalmaz szöveget
Karakterkódolás: us-ascii
Méret: 8 KB
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
uint8_t *know;
size_t persons;
uint8_t *team;
size_t teams;
int *diff;
int8_t *sign;
int8_t *sign_tmp;
int min;
} teams_t;
static void teams_init(teams_t *t)
{
t->know = 0;
t->persons = 0;
t->team = 0;
t->teams = 0;
t->diff = 0;
t->sign = 0;
t->sign_tmp = 0;
t->min = -1;
}
static void teams_free(teams_t *t)
{
if (t->sign_tmp)
free(t->sign_tmp);
if (t->sign)
free(t->sign);
if (t->diff)
free(t->diff);
if (t->team)
free(t->team);
if (t->know)
free(t->know);
}
static int teams_alloc(teams_t *t, size_t persons)
{
size_t i, p2 = persons * persons;
t->know = malloc(p2 * sizeof(uint8_t));
if (!t->know) {
fprintf(stderr, "Could not allocate memory for 'know'\n");
return 0;
}
for (i = 0; i < p2; i++)
t->know[i] = 0;
t->persons = persons;
t->team = malloc(persons * 2 * sizeof(uint8_t));
if (!t->team) {
fprintf(stderr, "Could not allocate memory for 'team'\n");
return 0;
}
for (i = 0; i < persons * 2; i++)
t->team[i] = 0;
t->teams = 0;
t->diff = malloc(persons * sizeof(int));
if (!t->diff) {
fprintf(stderr, "Could not allocate memory for 'diff'\n");
return 0;
}
t->sign = malloc(persons * sizeof(int8_t));
if (!t->sign) {
fprintf(stderr, "Could not allocate memory for 'sign'\n");
return 0;
}
t->sign_tmp = malloc(persons * sizeof(int8_t));
if (!t->sign_tmp) {
fprintf(stderr, "Could not allocate memory for 'sign_tmp'\n");
return 0;
}
return 1;
}
static inline int know_get(teams_t *t, size_t i, size_t j)
{
return *(t->know + i * t->persons + j);
}
static inline void know_set(teams_t *t, size_t i, size_t j, uint8_t v)
{
*(t->know + i * t->persons + j) = v;
}
static inline int know(teams_t *t, size_t a, size_t b)
{
return (know_get(t, a, b) != 0 && know_get(t, b, a) != 0);
}
static int teams_read(teams_t *t)
{
size_t persons, i, face;
if (scanf("%u", &persons) != 1) {
fprintf(stderr, "Wrong input\n");
return 0;
}
if (!teams_alloc(t, persons))
return 0;
for (i = 0; i < persons; i++)
while (1) {
if (scanf("%u", &face) != 1) {
fprintf(stderr, "Wrong input\n");
return 0;
}
if (face == 0)
break;
know_set(t, i, face - 1, 1);
}
return 1;
}
static int team_fill(teams_t *t, size_t i, uint8_t team)
{
size_t j;
uint8_t next = (team % 2 == 0) ? team + 1 : team - 1;
if (t->team[i] == team)
return 1;
if (t->team[i] == next)
return 0;
if (t->team[i] != 0)
return 1;
t->team[i] = team;
for (j = 0; j < t->persons; j++)
if (!know(t, i, j) && i != j)
if (!team_fill(t, j, next))
return 0;
return 1;
}
inline int abs(int x)
{
return (x >= 0) ? x : -x;
}
static int team_separate(teams_t *t)
{
size_t i, j, a, b;
for (i = 0; i < t->persons; i++) {
if (t->team[i] != 0)
continue;
if (!team_fill(t, i, 2 * t->teams))
return 0;
t->teams++;
}
for (i = 0; i < t->teams; i++) {
a = 0;
b = 0;
for (j = 0; j < t->persons; j++)
if (t->team[j] == 2 * i)
a++;
else if (t->team[j] == 2 * i + 1)
b++;
t->diff[i] = a - b;
}
return 1;
}
static void diff_calc(teams_t *t)
{
size_t i;
int sum = 0;
for (i = 0; i < t->teams; i++)
sum += t->diff[i] * t->sign_tmp[i];
if (t->min < 0 || t->min > abs(sum)) {
t->min = abs(sum);
memcpy(t->sign, t->sign_tmp, t->teams * sizeof(int8_t));
}
}
static void diff_backtrack(teams_t *t, size_t i)
{
size_t j;
for (j = i; j < t->teams; j++) {
if (abs(t->diff[j]) > 1)
break;
t->sign_tmp[j] = 0;
}
if (j == t->teams) {
diff_calc(t);
} else {
t->sign_tmp[j] = 1;
diff_backtrack(t, j + 1);
t->sign_tmp[j] = -1;
diff_backtrack(t, j + 1);
}
}
static void teams_min(teams_t *t)
{
diff_backtrack(t, 0);
}
int teams_cmp(const void *a, const void *b)
{
const uint8_t *t = a, *u = b;
return (int)*t - (int)*u;
}
void teams_write(teams_t *t)
{
uint8_t *team_a, *team_b, *team1_ptr, *team2_ptr;
size_t a = 0, b = 0, i, j, *team1_cnt, *team2_cnt;
team_a = malloc(t->persons * sizeof(uint8_t));
if (!team_a) {
fprintf(stderr, "Could not allocate memory for 'team_a'\n");
return;
}
team_b = malloc(t->persons * sizeof(uint8_t));
if (!team_b) {
fprintf(stderr, "Could not allocate memory for 'team_b'\n");
free(team_a);
return;
}
for (i = 0; i < t->teams; i++) {
if (t->diff[i] == 0) {
team1_ptr = team_a;
team1_cnt = &a;
team2_ptr = team_b;
team2_cnt = &b;
} else if (t->sign[i] > 0) {
team1_ptr = team_a;
team1_cnt = &a;
team2_ptr = team_b;
team2_cnt = &b;
} else if (t->sign[i] < 0) {
team1_ptr = team_b;
team1_cnt = &b;
team2_ptr = team_a;
team2_cnt = &a;
} else {
continue;
}
for (j = 0; j < t->persons; j++)
if (t->team[j] == 2 * i)
team1_ptr[(*team1_cnt)++] = j;
else if (t->team[j] == 2 * i + 1)
team2_ptr[(*team2_cnt)++] = j;
}
for (i = 0; i < t->teams; i++) {
if (t->sign[i] != 0 || abs(t->diff[i]) != 1)
continue;
if ((t->diff[i] > 0 && (int)a - (int)b < 0) ||
(t->diff[i] < 0 && (int)a - (int)b > 0)) {
team1_ptr = team_a;
team1_cnt = &a;
team2_ptr = team_b;
team2_cnt = &b;
} else {
team1_ptr = team_b;
team1_cnt = &b;
team2_ptr = team_a;
team2_cnt = &a;
}
for (j = 0; j < t->persons; j++)
if (t->team[j] == 2 * i)
team1_ptr[(*team1_cnt)++] = j;
else if (t->team[j] == 2 * i + 1)
team2_ptr[(*team2_cnt)++] = j;
}
qsort(team_a, a, sizeof(uint8_t), teams_cmp);
qsort(team_b, b, sizeof(uint8_t), teams_cmp);
printf("%d", a);
for (i = 0; i < a; i++)
printf(" %d", team_a[i] + 1);
printf("\n");
printf("%d", b);
for (i = 0; i < b; i++)
printf(" %d", team_b[i] + 1);
printf("\n");
free(team_b);
free(team_a);
}
int main(void)
{
teams_t t;
teams_init(&t);
if (!teams_read(&t)) {
teams_free(&t);
return 1;
}
if (!team_separate(&t)) {
printf("No solution\n");
} else {
teams_min(&t);
teams_write(&t);
}
teams_free(&t);
return 0;
}