题目大意:
给出n*n的矩阵Map,Map[i][j]代表第i个男人和第j个女人之间的满意度,求男女一一配对后,最大的满意度之和。
题目思路:状态压缩
题目可看做每行取一点,所有点不同列的情况下,各个点的最大和为多少。
dp[i][j],代表第i行,状态为j的情况下的最优解,其中j的含义为:j所代表的二进制数中:若第i位为1则取第i列的值,为0则不取。
这样j从1到(1<<n)-1,便包含了矩阵中所有列的取法
为了节约时间,我们需要作出一点优化:我们知道i*i的矩阵中不可能存在比i大的列,也就是说(i&(1<<k)应该大于0,k从0到n-1)。
得出状态转移方程式:dp[i][j]=max(dp[i][j],dp[i-1][j^(1<<k)]+Map[i][k+1])
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #define LL long long #define MAXSIZE 1005 using namespace std; int dp[20][100005],Map[MAXSIZE][MAXSIZE]; int Solve(int n) { memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++) { for(int j=1;j<(1<<n);j++) { int cnt=0; for(int k=0;k<n;k++)//优化时间 { if(j&(1<<k)) cnt++; } if(cnt!=i) continue; for(int k=0;k<n;k++) if(j&(1<<k)) dp[i][j]=max(dp[i][j],dp[i-1][j^(1<<k)]+Map[i][k+1]); } } return dp[n][(1<<n)-1]; } int main() { int T,cns=1,n; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&Map[i][j]); int ans=Solve(n); printf("Case %d: %d ",cns++,ans); } return 0; }