题目大意:
n对男女,现在要求将他们配对, 给你nxn的矩阵, 第i行第j列表示, 第i个男生和第j个女生配对的优先指数, 将n对男女全部配对的最大优先指数
参考题解:http://blog.csdn.net/guard_mine/article/details/46386421
定义dp[i][j] 表示第i个男生,状态为j时的最大值
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 0x3f3f3f3f;
int mp[23][23], dp[23][(1<<16)+7];
void solve()
{
int n;
scanf("%d",&n);
memset(mp, 0, sizeof(mp));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&mp[i][j]);
}
}
memset(dp, 0, sizeof(dp));
for(int i=1; i<=n; i++)
{
for(int j=0; j<(1<<n); j++)//枚举所有状态
{
int ans = 0;
for(int k=0; k<n; k++)
if(j & (1 << k))
ans ++;
if(ans != i-1)//过滤掉女生配对人数不为i-1的状态
continue;
for(int k=0; k<n; k++)
{
if(j & (1 << k))//已经找到没有找到女生的状态, 找到的过滤掉了
continue;
dp[i][j|(1<<k)] = max(dp[i][j|(1<<k)], dp[i-1][j] + mp[i][k+1]);
}
}
}
printf("%d\n",dp[n][(1<<n)-1]);
}
int main()
{
int T;
scanf("%d",&T);
for(int i=1; i<=T; i++)
{
printf("Case %d: ", i);
solve();
}
return 0;
}
优化一下,用空间换取时间
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 0x3f3f3f3f;
int mp[23][23], dp[23][(1<<16)+7];
set<int>st[17];
void init()
{
for(int i=0; i < (1<<16); i++)
{
int ans = 0;
for(int j=0; j<16; j++)
if(i & (1 << j))
ans ++;
st[ans].insert(i);
}
}
void solve()
{
int n;
scanf("%d",&n);
memset(mp, 0, sizeof(mp));
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&mp[i][j]);
}
}
memset(dp, 0, sizeof(dp));
for(int i=1; i<=n; i++)
{
for(set<int>::iterator it = st[i-1].begin(); it != st[i-1].end(); ++ it)
{
for(int k=0; k<n; k++)
{
if((*it) & (1 << k))
continue;
dp[i][(*it)|(1<<k)] = max(dp[i][(*it)|(1<<k)], dp[i-1][(*it)] + mp[i][k+1]);
}
}
}
printf("%d\n",dp[n][(1<<n)-1]);
}
int main()
{
int T;
scanf("%d",&T);
init();
for(int i=1; i<=T; i++)
{
printf("Case %d: ", i);
solve();
}
return 0;
}
队友的方法(很容易理解的一种):
#include<bits/stdc++.h>
using namespace std;
int mp[17][17], dp[17][1<<17];
int main()
{
int T;
scanf("%d",&T);
for(int _ = 1; _ <= T; _ ++)
{
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
scanf("%d",&mp[i][j]);
memset(dp, 0, sizeof(dp));
for(int i=1; i<=n; i++)
{
for(int j=0; j<n; j++)
{
for(int k=0; k<(1<<n); k++)
if((k & (1 << j)) == 0)
dp[i][k|(1<<j)] = max(dp[i][k|(1<<j)], dp[i-1][k] + mp[i][j+1]);
}
}
printf("Case %d: %d\n", _, dp[n][(1<<n)-1]);
}
return 0;
}