Problema del mejor partido del atleta | Retroceso: permutación N (poda máxima)

El problema del mejor partido del atleta

Los grados 10 hora de apertura Martes, 7 de abril de 2020 08:55
descuento 0,8 Tiempo de descuento Sábado, 30 de mayo de 2020 23:55
Se permite la presentación tardía No Hora de cierre Sábado, 30 de mayo de 2020 23:55

El equipo de bádminton tiene n jugadores masculinos y femeninos. Dadas dos n * n matrices P y Q. P [i] [j] es la ventaja competitiva de los jugadores masculinos en dobles mixtos entre el jugador masculino i y la jugadora j; Q [i] [ j] es la ventaja competitiva de las atletas femeninas en dobles mixtos entre la atleta i y el atleta masculino j. Debido a varios factores como la coordinación técnica y el estado psicológico, P [i] [j] no es necesariamente igual a Q [j] [i]. La ventaja competitiva del emparejamiento entre la atleta i y la atleta j es P [i] [j] * Q [j] [i]. Diseñar un algoritmo para calcular el mejor método de emparejamiento para atletas masculinos y femeninos para maximizar la suma de las ventajas competitivas de hombres y mujeres en cada grupo .

Entrada de datos: la primera línea tiene un número entero positivo n (1 <= n <= 12), las siguientes 2n líneas son P y Q

Salida de resultado: la suma de las ventajas competitivas de cada grupo del mejor partido 

  Entrada de prueba Rendimiento esperado límite de tiempo Limite de memoria Proceso extra
Caso de prueba 1  
  1. 3↵
  2. 10 2 3↵
  3. 2 3 4↵
  4. 3 4 5↵
  5. 2 2 2↵
  6. 3 5 3↵
  7. 4 5 1↵
 
  1. 52↵
1 segundo Los 64M 0

1. Pensando en retrospectiva

       Esta pregunta se pensó primero en la enumeración violenta, pero la enumeración bastante violenta que debe adoptar el método de marcha atrás. Obviamente, este es un modelo de retroceso de la disposición N .

       Primero calcule las ventajas del i-ésimo atleta masculino y la j-ésima atleta femenina en una matriz bidimensional pq [i] [j] , y luego seleccione n combinaciones en esta matriz bidimensional (la combinación corresponde a cada punto (i, j)), se requiere que n puntos no puedan estar en la misma fila o en la misma columna, sumar los n puntos calificados y registrar el valor máximo.

       El i-ésimo nivel de retroceso corresponde al i-ésimo atleta masculino En este nivel de retroceso se debe seleccionar una atleta que no haya sido seleccionada. Para registrar si la atleta femenina ha sido seleccionada , creamos una matriz vis [i]  para registrar y acumular las ventajas de cada capa por turno. Cuando i> n, es el final del retroceso, en este momento se actualiza la suma de la ventaja máxima.


En segundo lugar, la operación de poda más problemática

        La operación de poda del problema más grande es un poco más complicada que el problema más pequeño. Necesitamos calcular previamente la coincidencia máxima de la matriz pre [i] : 1 ~ i de atletas masculinos (de hecho, max: pq [i] [j]). Nota: Este partido más grande en realidad puede ser repetido por atletas femeninas, porque es solo para la elección codiciosa de los más grandes, para la conveniencia de la poda final.

    /* 贪心获取 1~i 男运动员匹配的最大情况:pre[i]
     * 注意:选择可以不合理(女运动员被重复选择),但是只是为了剪枝
     *      只要保证每次是贪心地选取,结果肯定比合理的情况更大 */
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++)
            pre[i] = max(pre[i], pq[i][j]);
        pre[i] += pre[i - 1];
    }

        Luego, en el i-ésimo nivel de retroceso, se han organizado los primeros 1 ~ i-1 atletas masculinos, y la ventaja de disposición de los siguientes en ~ n atletas masculinos no puede exceder pre [n] -pre [i -1]. Por lo tanto, podemos podarlo a través de esta función: si la ventaja actual más pre [n] -pre [i -1] no puede exceder el valor máximo registrado, entonces no hay necesidad de continuar buscando a lo largo de esta ruta. Bajar.


Tres, implementación de código

#include <cstdio>
#include <algorithm>

#define MAXN 13
using namespace std;

int n;
int p[MAXN][MAXN], q[MAXN][MAXN], pq[MAXN][MAXN];
int pre[MAXN] = {0}; // 0~i 男运动员匹配的最大情况
bool vis[MAXN] = {false};  //记录女运动员是否被访问过
int score = 0, best_score = 0;  //记录当前优势 与 当前最大优势

void backtrack(int i) {
    /* 回溯的终点 */
    if (i > n) {
        best_score = max(best_score, score);  //更新最大优势
        return;
    }

    /* 剪枝操作:就算后面都不合理贪心选择都不能超过 */
    if (score + pre[n] - pre[i - 1] < best_score)
        return;

    /* 在n个女运动员中选择 */
    for (int j = 1; j <= n; j++) {
        if (vis[j])   //女运动员已经被选择
            continue;

        vis[j] = true;
        score += pq[i][j];
        backtrack(i + 1);

        vis[j] = false;
        score -= pq[i][j];
    }
}

int main() {
    scanf("%d", &n);

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            scanf("%d", &p[i][j]);

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            scanf("%d", &q[i][j]);

    /* 计算得到总表 */
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            pq[i][j] = p[i][j] * q[j][i];
        
    /* 贪心获取 0~i 男运动员匹配的最大情况:pre[i]
     * 注意:选择可以不合理(女运动员被重复选择),但是只是为了剪枝
     *      只要保证每次是贪心地选取,结果肯定比合理的情况更大 */
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++)
            pre[i] = max(pre[i], pq[i][j]);
        pre[i] += pre[i - 1];
    }
    backtrack(1);
    printf("%d\n", best_score);
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43787043/article/details/106072396
Recomendado
Clasificación