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;
}