本文已参与[新人创作礼]活动,一起开启掘金创作之路
题目描述
这是4月24日代码源div2的每日一题。
最后的舞会 - 题目 - Daimayuan Online Judge
老师为即将毕业的同学们准备了一场舞会,有2N个同学会参加这场舞会,他们会被分成N对跳舞,每个人有一个编号,如果编号为i的同学和编号为j的同学配对,那么这一对的满意度是Ai,j(i<j),我们规定这个舞会的满意度为每一队的满意度的异或和,也就是说,当同学们分成N组后,第i对同学的满意度为Ai,那么舞会的满意度为A1⊕A2⊕...AN 请你求出本场舞会满意度的最大值
输入描述
第一行给出一个数N,有2N个人参加舞会
接下来给出一个矩阵表示i和j配对时的满意度
A1,2,A1,3,...A1,2N A2,3,...A2,2N . . . A2N−1,2N 其中1≤N≤8,0≤Ai,j≤2^30
输出描述
输出本场舞会满意度的最大值
样例输入
2
4 0 1
5 3
2
样例输出
6
样例解释
如果{1,2},{3,4},ans=A1,2⊕A3,4=4⊕2=6
如果{1,3},{2,4},ans=A1,3⊕A2,4=0⊕3=3
如果{1,4},{2,3},ans=A1,4⊕A2,3=1⊕5=4
最后答案为max(6,3,4)=6
问题解析
这题可以直接暴力写。
枚举所有的组合,算每次组合的满意度,并在过程中维护最大值。比如你从1开始,选一个和1搭配的,然后再从剩下的人里选一个去做下一队的配对。这里n最多是8,2* n人就是16,此过程每次取一对人出来,那么可能的组合数就是 15 * 13 * 11 * 9…… * 1,并不会超时。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50, MOD = 100003;
ll n, ans = 0, mx = 0;
vector<vector<ll>>v;
int mymap[20];
inline int read() {
long long x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
inline void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 | '0');
}
void dfs(int u, ll res, int x)
{
mymap[u] = 1;
for (int i = u + 1; i <= 2 * n; i++)
{
if (mymap[i] == 0)
{
ll ans = res ^ v[u][i];
mymap[i] = 1;
bool flag = true;
int j = 1;
for (; j < 2 * n; j++)
if (mymap[j] == 0)
break;
if (j < 2 * n)
{
mymap[j] = 1;
flag = false;
dfs(j, ans, x + 1);
mymap[j] = 0;
}
if (flag)
{
mx = max(mx, ans);
}
mymap[i] = 0;
}
}
mymap[u] = 0;
}
int main()
{
n = read();
int x;
int m = 2 * n;
v.push_back({ 0 });
for (int i = 1; i < m; i++)
{
vector<ll>v0(2 * n + 1);
for (int j = i + 1; j <= m; j++)
{
v0[j] = read();
}
v.push_back(v0);
}
dfs(1, 0, 0);
write(mx);
return 0;
}