hdoj 5045 期望dp

hdoj 5045

题意:火星的ACM比赛,一个队伍有若干名队员,每个题目只能一个小时由一个人完成,每个人对每个题目都有一个ac率,问最大的ac期望。限制是每一时刻任意两个人之间完成的题目数的差值不能超过1。

思路:一个比较简单的期望dp。因为每一时刻ac的题目数差距不能超过1,所以所有人都要同步ac题目,因为人数也不多,所以可以用位压缩来标识当前所有人题目完成情况,让没有完成题目的人去完成题目,那么dp[i][j | (1 << k)] = max(dp[i][j | (1 << k)], dp[i - 1][j] + pro[i][k]),前提是j&(1 << k)为0,即第k个人还没有完成题目。需要注意的是对于n个人,0和(1<<n)-1是一样的。

#include <cstdio>
#include <cstring>

inline double max(double a, double b){
    return a > b ? a : b;
}
double dp[1010][1024], pro[12][1010];
main() {
    int t;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; cas++) {
        int n, m;
        for(int i = 0; i < 1010; i++)
            for(int j = 0; j <1024; j++)
                dp[i][j] = -1;
        dp[0][0] = 0.0;
        scanf("%d %d", &n, &m);
        for(int i = 0; i < n; i++)
            for(int j = 1; j <= m; j++)
                scanf("%lf", &pro[i][j]);
     /*   for(int i = 0; i < n; i++) {
            dp[0][1 << i] = pro[i][0];
        }*/
        int p = 1 << n;
        for(int i = 0; i < m; i++) {
            for(int j = 0; j < p; j++) {
                if(dp[i][j] == -1) continue;
                for(int k = 0; k < n; k++) {
                    if(j == p - 1) {
                        dp[i + 1][1 << k] = max(dp[i + 1][1 << k], dp[i][j] + pro[k][i + 1]);
              //          printf("%d %d %f\n", i, i << k, dp[i + 1][1 << k]);
                    }
                    if((1 << k) & j) continue;
                    dp[i + 1][j | (1 << k)] = max(dp[i + 1][j | (1 << k)], dp[i][j] + pro[k][i + 1]);
                //    printf("%d %d %f\n", i + 1, j | (1 << k), dp[i + 1][j | (1 << k)]);
                }
            }
        }
        double ans = 0;
        for(int i = 0; i < p; i++) ans = max(ans, dp[m][i]);
        printf("Case #%d: %.5f\n", cas, ans);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值