Lo que está preguntando se llama Establecer problema de partición, que es un problema NP-hard, también conocido como el problema más fácil.
Cuando se saca a los niños de la escuela a jugar fútbol, por ejemplo, se seleccionan dos líderes de equipo de la clase que se turnan para seleccionar a los miembros de su equipo uno por uno. Ambos intentan maximizar la fuerza de sus equipos, terminan tratando de resolver un problema de partición de conjuntos (donde ambos conjuntos tienen un valor igual o más o menos igual) sin saberlo realmente. ¿Puedes adivinar fácilmente qué estrategia siguen?
Algoritmo que implementan sin saber que es lo que se llama un algoritmo codicioso codicioso, simplemente significa que eligen primero la mejor opción. Entonces, si una clase consta de 10 estudiantes con habilidades que varían en una escala del 1 al 10
considere esta matriz que denota las habilidades / fortaleza de esos 10 estudiantes
[4, 2, 5, 8, 7, 6, 3, 2, 2, 1]
los selectores del equipo harían lo siguiente
equipo 1 = {}
equipo 2 = {}
Paso 1
equipo 1 = {8}
equipo 2 = {}
Paso 2
equipo 1 = {8}
equipo 2 = {7}
Paso 3
equipo 1 = {8, 6}
equipo 2 = {7}
Etapa 4
equipo 1 = {8, 6}
equipo 2 = {7, 5}
Paso 6
equipo 1 = {8, 6, 4}
equipo 2 = {7, 5, 3}
Paso 8
equipo 1 = {8, 6, 4, 2}
equipo 2 = {7, 5, 3, 2}
Paso 10
equipo 1 = {8, 6, 4, 2, 2}
equipo 2 = {7, 5, 3, 2, 1}
la suma de habilidades del equipo 1 es 22 y el equipo 2 es 18
lo que deberíamos aprender de esto es que el método codicioso proporciona una buena aproximación pero puede no proporcionar la respuesta correcta que podría ser en este caso
equipo 1 = {2, 8, 6, 3, 1} = 20
equipo 2 = {4, 5, 7, 2, 2} = 20
Entonces, para una respuesta precisa, necesitamos algo más
Una heurística simple podría ser si tiene que dividir el conjunto en 2 conjuntos, la suma del conjunto inicial debe ser divisible por 2 o si tiene que dividir en n número de conjuntos, el resultado total_value del conjunto debe ser divisible por n
Una solución de programación dinámica podría ser encontrar si podemos hacer un subconjunto del conjunto dado que sume a 1 y construir nuestra solución sobre esto
El siguiente es el código de GeeksforGeeks para resolver este problema usando programación dinámica.
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
// Returns true if arr[] can be partitioned in two subsets of
// equal sum, otherwise false
bool findPartiion (int arr[], int n)
{
int sum = 0;
int i, j; // Caculcate sun of all elements
for (i = 0; i < n; i++)
sum += arr[i]; if (sum%2 != 0)
return false; bool part[sum/2+1][n+1]; // initialize top row as true
for (i = 0; i <= n; i++)
part[0][i] = true; // initialize leftmost column, except part[0][0], as 0
for (i = 1; i <= sum/2; i++)
part[i][0] = false; // Fill the partition table in botton up manner
for (i = 1; i <= sum/2; i++)
{
for (j = 1; j <= n; j++)
{
part[i][j] = part[i][j-1];
if (i >= arr[j-1])
part[i][j] = part[i][j] || part[i - arr[j-1]][j-1];
}
} /* // uncomment this part to print table
for (i = 0; i <= sum/2; i++)
{
for (j = 0; j <= n; j++)
printf ("%4d", part[i][j]);
printf("\n");
} */ return part[sum/2][n];
}
También debe leer el problema de Partición en Wikipedia para obtener una explicación.