方法:
求最大期望只需使得每一个题目匹配的人对应的概率的和最大即可。。。 所以进行多次二分图最大权匹配即可
PS:
初始化一定要注意处理好。。。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define eps 1e-9
#define maxn 12
double m_1[maxn][1111], m_2[maxn][maxn], lx[maxn], ly[maxn], d;
bool visx[maxn], visy[maxn];
int match[maxn], n, m;
void init()
{
memset(m_1, 0, sizeof(m_1));
scanf("%d %d",&n,&m);
for(int i= 1; i<= n; i++)
for(int j= 1; j<= m; j++)
scanf("%lf",&m_1[i][j]);
}
bool dfs(int u)
{
visx[u]= true;
for(int i= 1; i<= n; i++)
if(!visy[i])
{
double t= lx[u] + ly[i]- m_2[u][i];
if(t<= eps && t>= -eps)
{
visy[i]= true;
if(match[i]== -1 || dfs(match[i]))
{
match[i]= u;
return true;
}
}
else if(t> 0)
d= min(d, t);
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
for(int C= 1; C<= T; C++)
{
init();
double ans= 0;
for(int x= 1; x<= m; x+= n)
{
memset(match, -1, sizeof(match));
for(int i= 1; i<= n; i++)
{
lx[i]= ly[i]= 0;
for(int j= 1; j<= n; j++)
{
m_2[i][j]= m_1[i][x+j-1];
lx[i]= max(m_2[i][j], lx[i]);
}
}
d= 1<< 30;
for(int i= 1; i<= n; i++)
{
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
while(!dfs(i))
{
for(int j= 1; j<= n; j++)
{
if(visx[j]) lx[j]-= d;
if(visy[j]) ly[j]+= d;
}
memset(visx, false, sizeof(visx));
memset(visy, false, sizeof(visy));
}
}
for(int i= 1; i<= n; i++)
ans+= lx[i]+ ly[i];
}
printf("Case #%d: %.5lf\n",C,ans);
}
return 0;
}