在任意时刻,任意两个人的答题时间不能超过1小时。换句话说,就是每n道题要n个人轮流一遍(n是人数)。
状态压缩dp,dp[i][j] 表示答前i道题答题人员分配为 j 这个状态时的最大期望。
#include <iostream>
#include<stdio.h>
using namespace std;
int n,m;
double p[20][1010],dp[1010][1500],ans;
void init()
{
for(int i = 0;i <= m;i++)
for(int j = 0;j <= (1<<n);j++) dp[i][j] = -1;
dp[0][0] = 0;
}
void work()
{
init();
for(int i = 0;i < m;i++) //枚举第几题
{
for(int j = 0;j < 1<<n;j++)//枚举上一个状态
{
if(dp[i][j]<0)continue;
for(int k = 0;k < n;k++) //枚举当前第几人答题
{
if(((j>>k)&1)==0) //当前这个人没有答题
{
int tmp = j|(1<<k);
if(tmp == (1<<n)-1) tmp = 0;
if(dp[i][j]+p[k][i+1] > dp[i+1][tmp])
{
dp[i+1][tmp] = dp[i][j]+p[k][i+1];
}
}
}
}
}
}
int main()
{
int t;
scanf("%d",&t);
int cas = 1;
while(t--)
{
scanf("%d %d",&n,&m);
for(int i = 0;i < n;i++) //人编号从0开始,题目编号从1开始
for(int j = 1;j <= m;j++) scanf("%lf",&p[i][j]);
ans = 0;
work();
for(int i = 0;i < (1<<n);i++) if(dp[m][i] > ans) ans = dp[m][i];
printf("Case #%d: %.5lf\n",cas++,ans);
}
return 0;
}