B - 运动员最佳匹配问题------基于dfs的回溯思想

B - 运动员最佳匹配问题
Description
羽毛球队有男女运动员各n 人。给定2 个n×n 矩阵P 和Q。P[i][j]是男运动员i 和女运动员j配对组成混合双打的男运动员竞赛优势;Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势。由于技术配合和心理状态等各种因素影响,P[i][j]不一定等于Q[j][i]。男运动员i和女运动员j配对组成混合双打的男女双方竞赛优势为P[i][j]*Q[j][i]。
设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。
设计一个算法,对于给定的男女运动员竞赛优势,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。
Input
输入数据的第一行有1 个正整数n (1≤n≤20)。接下来的2n 行,每行n个数。前n行是p,后n行是q。
Output
将计算出的男女双方竞赛优势的总和的最大值输出。
Sample
Input

3
10 2 3
2 3 4
3 4 5
2 2 2
3 5 3
4 5 1

Output

52
#include<bits/stdc++.h>
using namespace std;
int mark,n;
int a[22][22];
bool vis[22];
int pre[22];//增加剪枝条件
void dfs(int p,int co)
{
    //jieshu
    if(p > n &&co > mark)
    {
        mark = max(co,mark);//mark :越来越高的要求
        return;
    }
    //jianzhi

    if(co + pre[n] - pre[p-1] > mark)//判断当前未选择的前提下,后面的优势
    {

        for(int i = 1; i <= n; i++)
        {
            if(vis[i] == false)
            {
                vis[i] =true;
                dfs(p+1,co+a[p][i]);
                vis[i] =false;
            }
        }
    }

}
int main()
{
    mark =0;
    scanf("%d",&n);
    for(int i=1; i<=n; i++)//1开始,防止越界 后面会出现 pre[p-1]
    {
        for(int j=1; j<=n; j++)
        {
            scanf("%d",&a[i][j]);
        }
        vis[i] =false;
    }
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            int x;
            scanf("%d",&x);
            a[j][i] *=x;

        }
    }

    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=n; j++)
        {
            pre[i] =max(a[i][j],pre[i]);//第i个理想的男方最大优势
        }
        pre[i] +=pre[i-1];//前i个理想的男方最大优势
    }

    dfs(1,0);
    printf("%d\n",mark);
}

cin、cout也可以

#include<bits/stdc++.h>
using namespace std;
int a[22][22];
int b[22][22];
int c[22][22];
int pre[22];//前..个男方优势
int vis[22];//标记女方
int tot;

void dfs(int p,int q,int sum)
{

    if(p > q && sum >tot)
    {
        tot=sum;
        return;
    }

    if(sum+pre[q]-pre[p-1] >tot)
    {
        for(int j =1; j<=q; j++)
        {
            if(vis[j] == 0)
            {
                vis[j] =1;
                dfs(p+1,q,sum+c[p][j]);//go 去确定下一个
                vis[j] =0;
            }
        }
    }

}
int main()
{
    int n;
    cin>>n;
    for( int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
        {
            cin>>a[i][j];
        }
    for( int i=1; i<=n; i++)
        for(int j=1; j<=n; j++)
        {
            cin>>b[i][j];
        }

    for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=n; j++)
        {
            c[i][j] = a[i][j]*b[j][i];
            pre[i]=max(pre[i],c[i][j]);
        }
        pre[i] +=pre[i-1];//前i个理想的男方最大优势
        }
    tot =0;
    dfs(1,n,0);//每个男方去确定一个女方,对女方标记

    cout<<tot<<endl;


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来杯Sherry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值