题目链接
题意
- 给我们 n 个男人和 n 个女人进行匹配,任意两个人之间进行匹配有一个权值,问怎样男女之间应该怎样匹配使总权值和最大
思路
- 这明显是一个二分图最大权匹配,可以用 KM 算法去做也可以用网络流去做,
- 由于 n<=16 , 这一题甚至可以 dfs 去做,当然也可以同 状压 dp 去做,这里说一下怎么用状压 dp 去做,
- 看数据范围应该可以考虑到状压 dp,
- 但是这题我们要想的是应该怎么去状压 dp,去状态转移呢?
- 其实首先我们进行状态转的时候,我们不知道、也不法确定 第 x 个男人要跟那个女人进行匹配,那么索性就让第 x 男人暴力的 1~n 中的女人进行匹配,然后从之前最优的的(x-1) 个男人的匹配状态进行转移,
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8ba55088b91acfe3e8611e8e7e23de7a.png)
代码
#include <bits/stdc++.h>
using namespace std;
#define db double
#define ll long long
#define sc scanf
#define pr printf
#define fi first
#define se second
#define pb push_back
#define m_p make_pair
#define Pir pair<int, int>
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
const int N = 16;
int a[N][N], dp[1 << N];
int main()
{
int T, cas = 1; sc("%d", &T);
while (T --)
{
int n; sc("%d", &n);
for (int i = 0; i < n; i ++)
for (int j = 0; j < n; j ++)
sc("%d", &a[i][j]);
memset(dp, 0, sizeof dp);
int S = (1 << n) - 1;
for (int i = 0; i < S; i ++)
{
int num = 0;
for (int j = 0; j < n; j ++) if (i & (1 << j)) num ++;
for (int j = 0; j < n; j ++)
{
if ((i & (1 << j)) == 0)
dp[i | (1 << j)] = max(dp[i | (1 << j)], dp[i] + a[num][j]);
}
}
pr("Case %d: %d\n", cas ++, dp[S]);
}
return 0;
}