链接:Wannafly挑战赛8 - C 小C打比赛
题意:
题目描述
小C现在要参加一场wannafly挑战赛,一场挑战赛一共有n道题,一共有m分钟。
对于第i道题,小C解决它需要恰好j分钟的概率是p i,j。
小C每次会选择某一道没做完的题,然后把它解决(不能中途放弃),之后再决策下一道要做的题是哪道。
求小C在最优策略下,期望能做出几道题。
对于第i道题,小C解决它需要恰好j分钟的概率是p i,j。
小C每次会选择某一道没做完的题,然后把它解决(不能中途放弃),之后再决策下一道要做的题是哪道。
求小C在最优策略下,期望能做出几道题。
输入描述:
第一行两个正整数n,m 接下来一共n行,每行有m个小数,第i行的第j个小数表示pi,j(这里假设不存在0分钟A题的dalao)。
输出描述:
输出一个小数,表示期望能做出几道题,保留小数点后五位。
示例1
输入
2 5 0.2 0.2 0.2 0.2 0.2 0 0.25 0.25 0.25 0.25
输出
1.30000
备注:
1≤ n≤ 6,1≤ m≤ 180 每道题的概率和为1(每道题只要时间够一定能做出来) 输入最多四位小数
题解:状压DP,dp[i][j]表示集题目集合为i时间为j的期望。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 6 + 10;
const int maxm = 180 + 10;
int n, m;
double p[maxn][maxm];
double dp[1<<maxn][maxm];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%lf", &p[i][j]);
for(int i = 1; i < (1 << n); i++){
for(int j = 1; j <= m; j++){
for(int k = 0; k < n; k++){
if((i >> k) & 1){
double tmp = 0;
for(int l = 1; l <= j; l++){
tmp += p[k+1][l] * (1 + dp[i ^ (1<<k)][j-l]);
}
dp[i][j] = max(dp[i][j], tmp);
}
}
}
}
printf("%.5f\n", dp[(1<<n)-1][m]);
return 0;
}