题干:
链接:https://ac.nowcoder.com/acm/contest/882/F
来源:牛客网
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 maximized.
Total competitive value is the summation of competitive value of each pair of people in different team.
The equivalent equation is ∑i=12N∑j=i+12N(vij if i-th person is not in the same team as j-th person else 0)\sum_{i=1}^{2N} \sum_{j=i+1}^{2N} (v_{ij} \text{ if i-th person is not in the same team as j-th person else } 0 )∑i=12N∑j=i+12N(vij 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.
Following 2N lines each contains 2N space-separated integers vijv_{ij}vij is the j-th value of the i-th line which indicates the competitive value of person i and person j.
* 1≤N≤141 \leq N \leq 141≤N≤14
* 0≤vij≤1090 \leq v_{ij} \leq 10^{9}0≤vij≤109
* vij=vjiv_{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
题目大意:
时限4秒。
将2*n个人分到两个team,每个team必须恰好有n个人,如果i,j两个人位于不同的team,那么收益增加 a[i][j],求分配的最大收益
第一行输入n
第二行输入一个(2*n)*(2*n)的矩阵。
求最大收益。
解题报告:
最暴力的方法是C(2*n,n)枚举,但是最后对于每一种情况算答案的时候需要n^2处理,这样总复杂度就是O( C(2*n,n) * n^2 ),在n=14的情况下是会T的。想办法优化掉一个N。( C(28,14) = 40116600)
可以这么转化一下问题,其实可以看成本来2*n个人都在一个team中,现在要拽其中一些人去另一个team,所以每当拽一个人去另一个team的时候,就减去对应的贡献。这样的好处就是,把最后统计需要On^2的时间均摊到每一次的dfs中线性完成,这样总复杂度就是O( C(2*n,n) * n ),可以接受。这题时限4秒。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
const ll mod = 1e9 + 7;
ll ma;
vector<int> v;
int n;
ll a[33][33],d[33];//d[i]代表i和其他所有点连边的权值和。
void dfs(ll x,ll ans) {
if(v.size()==n) {
ma = max(ma,ans); return ;
}
if(v.size()>n || x>=2*n) return ;
ll now=d[x];
for(auto s:v) now -= a[x][s]*2;
//选
v.push_back(x);
dfs(x+1,ans+now);
//不选
v.pop_back();
dfs(x+1,ans);
}
int main()
{
scanf("%d",&n);
for(int i=0; i<2*n; i++)
for(int j=0; j<2*n; j++) {
scanf("%lld",&a[i][j]);
d[i]+=a[i][j];
}
dfs(0,0);
cout << ma <<endl;
return 0 ;
}