Dance(400)异或,dfs,剪枝 AtCoder Beginner Contest 236

D - Dance /
Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 400 points

Problem Statement
2N people numbered 1,2,…,2N attend a ball. They will group into N pairs and have a dance.

If Person i and Person j pair up, where i is smaller than j, the affinity of that pair is A
i,j

.
If the N pairs have the affinity of B
1

,B
2

,…,B
N

, the total fun of the ball is the bitwise XOR of them: B
1

⊕B
2

⊕⋯⊕B
N

.

Print the maximum possible total fun of the ball when the 2N people can freely group into N pairs.

Constraints
1≤N≤8
0≤A
i,j

<2
30

All values in input are integers.
Input
Input is given from Standard Input in the following format:

N
A
1,2

A
1,3

A
1,4

⋯ A
1,2N

A
2,3

A
2,4

⋯ A
2,2N

A
3,4

⋯ A
3,2N


A
2N−1,2N

Output
Print the maximum possible total fun of the ball.

Sample Input 1
Copy
2
4 0 1
5 3
2
Sample Output 1
Copy
6
Let {i,j} denote a pair of Person i and Person j. There are three ways for the four people to group into two pairs, as follows.

Group into {1,2},{3,4}. The total fun of the ball here is A
1,2

⊕A
3,4

=4⊕2=6.
Group into {1,3},{2,4}. The total fun of the ball here is A
1,3

⊕A
2,4

=0⊕3=3.
Group into {1,4},{2,3}. The total fun of the ball here is A
1,4

⊕A
2,3

=1⊕5=4.
Therefore, the maximum possible total fun of the ball is 6.

Sample Input 2
Copy
1
5
Sample Output 2
Copy
5
There will be just a pair of Person 1 and Person 2, where the total fun of the ball is 5.

Sample Input 3
Copy
5
900606388 317329110 665451442 1045743214 260775845 726039763 57365372 741277060 944347467
369646735 642395945 599952146 86221147 523579390 591944369 911198494 695097136
138172503 571268336 111747377 595746631 934427285 840101927 757856472
655483844 580613112 445614713 607825444 252585196 725229185
827291247 105489451 58628521 1032791417 152042357
919691140 703307785 100772330 370415195
666350287 691977663 987658020
1039679956 218233643
70938785
Sample Output 3
Copy
1073289207

题意 :

  • 有2n个人,要分成n对,已知任意两人之间的好感值,求如何分配使得好感值异或和最大

思路 :

  • 发现数据范围很小,足够列举所有将2n个人分成n对的情况,然后输出其中最大的结果
  • 但如果分别考虑这2n个位置,时间复杂度有 16 ∗ 15 ∗ 14 ∗ . . ∗ 1 > 2 ∗ 1 0 13 16 * 15 * 14 * .. * 1 > 2*10^{13} 161514..1>21013,会超时
  • 我们发现,考虑当前一对时,我们只要都让这对中第一个位置是当前可以使用的人中最小的编号,然后枚举第二个位置求最大值,这样也可以遍历出所有的情况(因为我们只求最大值,不是求具体方案),这样,时间复杂度就优化成 15 ∗ 13 ∗ 11 ∗ . . . ∗ 1 = 2027025 15 * 13 * 11 * ... * 1 = 2027025 151311...1=2027025
  • 更妙的是,发现题目给我们的数据也是 小的编号-大的编号,这样我们枚举之后要计算当前结果只要直接用这个数组就可以了,不需要再复制一份数组

语法 :

  • 因为vec内容存的是pair,因此当其中有n对时,就是vec.size() == n,也就是说,判断vector容器的size,要根据它存的内容的类型,以一个内容物为一个单位
#include <iostream>
#include <vector>
using namespace std;

typedef pair<int, int> PII;

const int N = 20;

int n;
int a[N][N];
bool st[N];
vector<PII> vec;

int calc()
{
    if (vec.size() == n)
    {
        int ret = 0;
        for (auto p : vec) ret ^= (a[p.first][p.second]);
        return ret;
    }
    
    int l;
    for (int i = 1; i <= 2 * n; i ++ )
        if (!st[i])
        {
            l = i; break;
        }
    st[l] = true;
    
    int ret = 0;
    for (int i = 1; i <= 2 * n; i ++ )
        if (!st[i])
        {
            vec.push_back({l, i});
            st[i] = true;
            ret = max(ret, calc());
            st[i] = false;
            vec.pop_back();
        }
    
    st[l] = false;
    return ret;
}

int main()
{
    cin >> n;
    for (int i = 1; i <= 2 * n - 1; i ++ )
        for (int j = i + 1; j <= 2 * n; j ++ )
            cin >> a[i][j];
    
    cout << calc();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值