题目描述
Given 2 N 2N 2N people, you need to assign each of them into either red team or white team such that each
team consists of exactly N N N people and the total competitive value is maximized.
Total competitive value is the summation of competitive value of each pair of people in different team.
The equivalent equation is ∑ i = 1 2 N ∑ j = i + 1 2 N v i j \sum_{i=1}^{2N}\sum_{j=i+1}^{2N}v_{ij} ∑i=12N∑j=i+12Nvij(if i-th person is not in the same team as j-th person else 0)
输入描述
The first line of input contains an integers N N N.
Following 2 N 2N 2N lines each contains 2 N 2N 2N space-separated integers v i j v_{ij} vij
- 1 ≤ N ≤ 14 1\leq N\leq 14 1≤N≤14
- 0 ≤ v i j ≤ 1 0 9 0 \leq v_{ij} \leq 10^9 0≤vij≤109
- v i j = v j i v_{ij}=v_{ji} vij=vji
输出描述
Output one line containing an integer representing the maximum possible total competitive value.
示例1
输入 |
---|
1 |
0 3 |
3 0 |
输出 |
3 |
题目大意
一只球队总共有 2 × n 2\times n 2×n个队员,每两个队员之间都有一个竞争值,将 2 × n 2\times n 2×n个队员分成两组,使得不同组队员之间竞争值和最大。
解题思路
拿到这道题的时候就想到了全排列,也就是暴力搜索, N N N最大为14,那么时间复杂度就是 C ( 28 , 14 ) C(28,14) C(28,14),值在 4 e 7 4e7 4e7左右,那么接下来就是计算所有情况下的竞争值总和,如果直接用双层循环来计算的话,时间复杂度 O ( n 2 ) O(n^2) O(n2),即 196 196 196,直接会炸掉,所以不能在得到分组结果之后才进行计算竞争值之和,这样会付出更多的时间代价。而正解应该是一边进行分组,一边进行计算。
AC代码
#include<bits/stdc++.h>
#define _MATH_DEFINES_DEFINED
const int Max_N=1e5+10;
const int mod=998244353;
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int team[30][30];
int team1[30];
int team2[30];
ll res=0;
int n;
void dfs(int num1,int num2,int pos,ll maxres)
{
if(pos==2*n)
{
res=max(res,maxres);
}
if(num1<n)
{
team1[num1]=pos;
ll v=maxres;
for(int i=0;i<num2;i++)
v+=team[pos][team2[i]];
dfs(num1+1,num2,pos+1,v);
}
if(num2<n)
{
team2[num2]=pos;
ll v=maxres;
for(int i=0;i<num1;i++)
v+=team[pos][team1[i]];
dfs(num1,num2+1,pos+1,v);
}
return ;
}
int main()
{
cin>>n;
for(int i=0;i<2*n;i++)
{
for(int j=0;j<2*n;j++)
{
cin>>team[i][j];
}
}
dfs(0,0,0,0);
cout<<res<<endl;
}
总结
暴力的题目不能过分依赖 S T L STL STL的函数,手写 d f s dfs dfs并加入优化的过程会得到意想不到的结果。