zoukankan      html  css  js  c++  java
  • CF16E Fish 状压DP

    CF16E Fish

    ​ 状压DP;

    ​ 由于(n <= 18),我们可以状态压缩.

    ​ 一个二进制数第(i)位为1表示当前第(i)条鱼还活着.(f[x])表示当前局面为(x)的概率是多少.

    ​ 所以我们可以得出初始状态(f[1 << n - 1] = 1),因为刚刚开始所有鱼都活着,概率肯定为1.我们要求的状态是(f[x]),(x)中只有一个1的局面,因为只剩下一条鱼.

    ​ 然后我们开始转移:(f[x]) 要从 (f[x | (1 << i)])转移过来,(x)中第(i)为位0,表示第(i)条鱼这次被吃掉了.然后我们需要乘上发生这个事件的概率是多少,注意这里有一个坑点:我一开始只是将(x)中1的个数((num))统计了出来,然后自然地想到这条鱼被吃的概率就是(frac{1}{num}).结果一直不对,后来仔细一想,其实每两条鱼之间都会发生吃或被吃,所以这条鱼被吃的概率应该是(frac{1}{(num + 1){num} / 2}).

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int n;
    double f[300005], a[20][20];
    
    int main() {
    
        cin >> n;
        for(int i = 1;i <= n; i++)
            for(int j = 1;j <= n; j++) cin >> a[i][j];
        f[(1 << n) - 1] = 1;
        for(int i = (1 << n) - 1;i >= 1; i--) {
            for(int j = 0;j < n; j++) {
                if(!(i & (1 << j))) {
                    int k = i | (1 << j), num = 0; double tmp = 0; 
                    for(int l = 0;l < n; l++) {
                        if(k & (1 << l)) tmp += a[l + 1][j + 1], num ++;
                    }
                    f[i] += f[k] * tmp * 1.0 / (num * (num - 1) / 2); 
                    //上面的num是x中1的个数,这里的num是x | (1 << j)里面1的个数,所以稍微有点区别
                }
            }
        }
        for(int i = 0;i < n; i++) printf("%.6lf ", f[(1 << i)]);
    
        return 0;
    }
    
  • 相关阅读:
    Element 更新以及全局设置属性
    第二次作业
    软件工程---自我介绍
    git lfs
    SUID
    G1 log 解析
    CMS jvm flags详解
    java不安全证书报证书路径找不到问题
    记一次CMS unloading class 耗时长调查
    springboot jsp 在Linux中报404问题
  • 原文地址:https://www.cnblogs.com/czhui666/p/13905076.html
Copyright © 2011-2022 走看看