第23次CSP第四題 CSP202109-4 收集卡牌 100分(狀壓DP)


upd:
破案了,最后格式控制輸出%.10lf才能過,%.8lf會WA,估計是ccf賽時測評和賽后的測評機不太一樣..?

狀壓DP。下面的代碼交上去0分,比賽寫的暴力交上去也是0分,懷疑題庫數據炸了2333不過下面的和暴搜拍過小數據是沒問題的。等過一陣再試試。

#include <iostream>
using namespace std;
int n, k;
double p[200005];
double dp[400005][205];//dp[i][j]為i狀態下手中有j個硬幣的概率
double ans = 0;
int get(int x) {
    int ret = 0;
    while(x) {
        ret += (x & 1);
        x >>= 1;
    }
    return ret;
}
int main() {
    cin >> n >> k;
    
    for(int i = 0; i <= 200005; i++) {
        for(int j = 0; j <= 10; j++) {
            dp[i][j] = 0;
        }
    }
    for(int i = 0; i <= 100; i++) {
        dp[0][i] = 1;
    }
    for(int i = 1; i <= n; i++) {
        cin >> p[i];
    }
    for(int i = 1; i < (1 << n); i++) {
        for(int j = 0; j <= k * n; j++) {
            //直接抽卡獲得
            for(int k = 0; k < n; k++) {
                if(((i >> k) & 1) && !(get(i ^ (1 << k)) == 0 && j)) {//不可能從dp[0][x]轉移過來
                    int pre = i ^ (1 << k);
                    if(dp[pre][j] >= 0) dp[i][j] += dp[pre][j] * p[k + 1];
                }
            }
            //沒抽到
            for(int k = 0; k < n; k++) {
                if(j != 0 && ((i >> k) & 1)) {
                    if(dp[i][j - 1] >= 0) {
                        dp[i][j] += dp[i][j - 1] * p[k + 1];
                        
                    }
                }
            }
            int num = get(i);
            if(num == n || num + (j / k) >= n) {//滿足條件才能更新答案
                ans = ans + dp[i][j] * (num + j);
                dp[i][j] = -1;//到此為止 不會繼續抽了
            }
        }
    }
    printf("%.10lf", ans);//%.10lf沒問題 %.8lf會0分
    return 0;
}
// 10 7
// 0.1 0.1 0.2 0.05 0.05 0.02 0.08 0.2 0.1 0.1
// 10 5
// 0.03 0.07 0.26 0.04 0.1 0.16 0.17 0.07 0.04 0.06


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM