Partition problem(dfs)

给定2N个人,需要将他们分配到红队和白队,每个队各N人,目标是最大化两个队伍之间的竞争价值总和。输入包含每个人之间的竞争值,输出最大竞争价值。采用深度优先搜索(DFS)策略寻找最佳分配方案。

 F-Partition problem_2019⽜客暑期多校训练营(第⼆场)
https://ac.nowcoder.com/acm/contest/882/F 1/1
 Partition    problem
时间限制:C/C++    4秒,其他语言8秒 空间限制:C/C++    262144K,其他语言524288K 64bit    IO    Format:    %lld
题目描述    
Given    2N    people,    you    need    to    assign    each    of    them    into    either    red    team    or    white    team    such    that    each    team    consists    of    exactly    N    people    and    the    total    competitive    value    is    max
Total    competitive    value    is    the    summation    of    competitive    value    of    each    pair    of    people    in    different    team.
输入描述:

The first line of input contains an integers N.
Following 2N lines each contains 2N space-separated integers vij  indicating the competitive value of person i and person j.
1 ≤ N ≤ 14

0 ≤ vij ≤ 10的九次方

vij = vji
输出描述:

Output one line containing an integer representing the answer.
示例1
输入
1

0 3   //0对0的竞争价值为0,0对1的竞争价值为3

3 0  //1对0的竞争价值为3,1对1的竞争价值为0
输出
3

这个题的题意是一共2*n个人,告诉你每个人对另一个人的竞争价值,让你把他们分配成每队n个人的两个队伍,求一个队伍最大的总的竞争价值,主要是找使一个队伍总的竞争价值最大的方案,队伍总的竞争价值为每个人的竞争价值的总和(每个人的竞争价值为:每个人对另一个队每个人的竞争价值的总和),所以用dfs遍历所有分配方案,然后在其中找出最大竞争价值就行了

完整代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,ans,v[100][100];
int t1[100],t2[100];//t1[],t2[]分别保存红队和白队所有人的编号,如:t1[0]=3表示红队第一个人的编号为3
void dfs(int now,int num1,int num2,int sum)//now为当前人的编号,num1为红队当前人数(第几个人),num2为白队当前人数,sum为当前队伍总的竞争价值
{
    if(num1==n&&num2==n)//每个队n个人时为一种分配方案
    {
        ans=max(ans,sum);
        return;
    }
    int add=0;
    if(num1<n)//如果红队当前人数<总人数,就把当前人的编号now归到红队
    {
        for(int i=0;i<num2;i++)
        {
            add+=v[now][t2[i]];//add计算当前人对另一个队的竞争价值的总和
        }
        t1[num1]=now;//把当前编号为now的这个人归到红队
        dfs(now+1,num1+1,num2,sum+add);//继续找下一个人
    }
    add=0;
    if(num2<n)//同上
    {
        for(int i=0;i<num1;i++)
        {
            add+=v[now][t1[i]];
        }
        t2[num2]=now;
        dfs(now+1,num1,num2+1,sum+add);
    }
}

signed main()
{
    scanf("%lld",&n);
    for(int i=0;i<2*n;i++)
    {
        for(int j=0;j<2*n;j++)
        {
            scanf("%lld",&v[i][j]);
        }
    }
    dfs(0,0,0,0);
    printf("%lld\n",ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值