题解 | Partition problem-2019牛客暑期多校训练营第二场F题

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss
题目描述:
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 = 1 2 N \sum_{i=1}^{2N} i=12N ∑ j = i + 1 2 N \sum_{j=i+1}^{2N} 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 vij is the j-th value of the i-th line which indicates the competitive value of person i and person j.

1≤N≤14
1≤vij≤109
vij=vji

输出描述:
Output one line containing an integer representing the maximum possible total competitive value.

示例1:
输入
1
0 3
3 0

输出
3

题解:
• Brute force
There are C(2N, N) ways of assignments. For each assignment, the cost can be calculated in O(N^2).
Results in O(C(2N, N) N^2) time complexity.

• Brute force
O(C(2N, N) N^2) may NOT be fast enough.
You can solve it in O(C(2N, N) N).
First, put all people in one team. The value will be 0.
Whenever pull one people to another team, we can compute the delta of the value. In each step, it takes O(N).

代码:

#include <bits/stdc++.h>
using namespace std;
constexpr int N = 18;
typedef long long LL;
int n, all;
LL v[N + N][N + N], ans;
void go(int msk, int got, int pre, LL cst) {
  if (got + got == n) {
    ans = max(ans, cst);
    return;
  }
  if (n - pre - 1 + got < n / 2) {
    return;
  }
  for (int nxt = pre + 1; nxt < n; ++ nxt) {
    LL nxt_cst = cst;
    for (int i = 0; i < n; ++i) {
      if ((msk >> i) & 1)
        nxt_cst -= v[nxt][i];
      else
        nxt_cst += v[nxt][i];
    }
    go(msk | (1 << nxt), got + 1, nxt, nxt_cst);
  }
}
int main() {
  cin >> n;
  n <<= 1;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      cin >> v[i][j];
    }
  }
  all = (1 << n) - 1;
  LL cst = 0;
  for (int i = 0; i < n; ++i) {
    cst += v[0][i];
  }
  go((1 << 0), 1, 0, cst);
  printf("%lld\n", ans);
}

更多问题,更详细题解可关注牛客竞赛区,一个刷题、比赛、分享的社区。
传送门:https://ac.nowcoder.com/acm/contest/discuss

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值