题意:一个比赛,n个人搞,有m道题,只能按顺序交题,每题只能一个人去A,给出每个人A每道题的概率。但是为了公平,在任何时刻不能有人比另一个人多做1道题以上。
思路:状压DP。10个人,用10位二进制数表示。如果当前某人多做了题,那一位就是1,否则是0,不允许多做两题及以上的状态出现,还有如果是“全1”的状态,直接置为“全0”。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string.h>
#include <ctype.h>
using namespace std;
#define ll long long
double dp[1025][1010];
double a[12][1025];
int main(){
int t;
cin>>t;
int cas=0;
while(t--){
cas++;
int n,m;
cin>>n>>m;
//init
for(int i=0;i<=1024;i++){
for(int j=0;j<=m;j++){
dp[i][j]=-1.0;
}
}
dp[0][0]=0.0;
//
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lf",&a[i][j]);
}
}
int full=(1<<n)-1;
double ans=0.0;
for(int j=1;j<=m;j++){
for(int i=0;i<full;i++){
for(int k=1;k<=n;k++){
int cur=1<<(k-1);
if(dp[i][j-1]<0)continue;
//cout<<cur<<"...."<<i<<endl;
if(cur&i)continue;
int newi=i|cur;
if(newi==full)newi=0;
dp[newi][j]=max(dp[newi][j],dp[i][j-1]+a[k][j]);
if(j==m)ans=max(ans,dp[newi][j]);
}
}
}
printf("Case #%d: %.5lf\n",cas,ans);
}
return 0;
}