题解:我们使用一个二位数组dp[i][j]记录进行到第i个任务时,人组合为j时的最大和(这里的j我们用二进制的每位相应一个人)。
详细见代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long ll; double s[11][1010]; double dp[1010][1050]; double work(int m,int n) { int k=(1<<m)-1; for(int i=2; i<=n; i++) { for(int l=0,r=0; l<k; l++) { if(dp[i-1][l]) for(int j=0; j<m; j++) { r=1<<j; if(l&r) continue; dp[i][l|r]=max(dp[i][l|r],dp[i-1][l]+s[j+1][i]); } } if(dp[i-1][k]) //j==k时单独处理,相当于已经运行完一轮之后的第一个任务 for(int j=0,r=0; j<m; j++) { r=1<<j; dp[i][r]=max(dp[i][r],dp[i-1][k]+s[j+1][i]); } } double ans=0; for(int i=0; i<=k; i++) ans=max(ans,dp[n][i]); return ans; } int main() { int cas,m,n; scanf("%d",&cas); for(int ca=1; ca<=cas; ca++) { memset(dp,0,sizeof(dp)); scanf("%d%d",&m,&n); for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) scanf("%lf",&s[i][j]); dp[1][1<<(i-1)]=s[i][1]; } printf("Case #%d: %.5lf ",ca,work(m,n)); } return 0; }