题意:ACM比赛过程中有n个人,m题,给出每人做出每道题的概率,并且在任何时刻任意两个人做题的数量不能相差超过2(从第一题往后面做),求做出题最大数量的期望。
思路:状态压缩。因为不能超过2,所以当一个人做出来一道题了以后,他必须等所有人都做了一道题以后才能再做一道题。一个人做出来一题以后就把他的那一位置1,n个0和n个1是一样的。
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
double dp[1005][1<<11];
double pos[15][1005];
int main()
{
//freopen("data.txt","r",stdin);
int T;
scanf("%d",&T);
int kase=0;
while(T--)
{
printf("Case #%d: ",++kase);
// cout<<endl;
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
for(int j=1;j<=m;++j)
{
scanf("%lf",&pos[i][j]);
}
}
for(int j=0;j<=m;++j)
for(int i=0;i<(1<<n);++i)
{
if(j!=0||i!=0)
dp[j][i]=-9.0;
else dp[i][j]=0.0;
}
int all=(1<<n)-1;
for(int i=1;i<=m;++i)
{
for(int j=0;j<=(1<<n)-1;++j)
{
for(int k=1;k<=n;++k)
{
if(j&(1<<(k-1)))
{
int ss=j-(1<<(k-1));
if(dp[i-1][ss]<0)continue;
dp[i][j]=max(dp[i][j],dp[i-1][ss]+pos[k][i]);
}
}
}
dp[i][0]=dp[i][all];
}
double ans=0;
for(int i=0;i<=all;++i)
{
ans=max(ans,dp[m][i]);
}
printf("%.5lf\n",ans);
}
return 0;
}