標籤:
意甲冠軍:
n一定長度m串 隱藏的字串相等的機率 然後,你猜怎麼著玩家隱藏的字串 的詢問字串的一個位置 再不斷的知道一些位置後 遊戲者就能夠確定藏起來的串是什麼 問 遊戲者的期望步數
思路:
能夠說是一道機率題 也能夠說是期望題 總之感覺題目不錯…
首先假設我們枚舉藏起來的串是哪個(複雜度n) 然後利用狀壓去dp維護猜某些位的狀態的機率 以及對於那個狀態剩下哪些串是無法辨別的(複雜度m*2^m) 那麼複雜度為 O(nm2^m) 這樣就會TLE
接著思考 事實上問題不是出在狀壓的2^m上(它已經非常優秀了) 既然不去掉狀壓 那麼輔助狀態轉移的m也扔不掉 我們僅僅能想方法避免那個n 使複雜度達到 O(m2^m)
然後我們來確定方案:
我們用狀壓的位元表示m個位置有哪些位置已經被揭示了 那麼我們能夠利用dp求出對於每一個狀態的機率(或者稱為從一位都不揭示到揭示到如今這樣的狀態的期望) 那麼對於如今這樣的狀態 假設已經能夠猜到藏起來的是哪個串 那麼我們就不須要再猜了 否則至少要猜下一步 那麼這個“下一步”對於整個遊戲期望步數的貢獻就為dp[狀態]*1
如今問題就在 怎樣推斷這個狀態是不是猜完了
事實上這個問題能夠用dp打表出 對於已經猜了一些位置後 有哪些串是如今的狀態分辨不出來的(代碼中的f數組)
那麼假設f為0 表示已經猜到了 假設不為0則裡面至少有2個1存在 則對於當中的每一個1 假設藏起來的正是1相應的那個串 則還須要1步 那麼這1步對答案的貢獻就是剛才說的dp[]*1了
代碼:
#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<map>#include<set>#include<vector>#include<queue>#include<cstdlib>#include<ctime>#include<cmath>#include<bitset>using namespace std;typedef long long LL;#define N 55#define M 25int n, len;char str[N][M];LL f[(1 << 20) + 10], bin[N];double ans[(1 << 20) + 10];double res;int main() {int i, j, k, c;bin[0] = 1;for (i = 1; i < N; i++)bin[i] = (bin[i - 1] << 1);scanf("%d", &n);for (i = 0; i < n; i++)scanf("%s", str[i]);len = strlen(str[1]);for (i = 0; i < n; i++) {for (j = 0; j < n; j++) {if (i != j) {int same = 0;for (k = 0; k < len; k++) {if (str[i][k] == str[j][k])same |= bin[k];}f[same] |= bin[j];}}}for (i = bin[len] - 1; i >= 0; i--) {for (j = 0; j < len; j++) {if (i & bin[j]) {f[i ^ bin[j]] |= f[i];}}}ans[0] = 1;for (i = 0; i < bin[len]; i++) {for (c = j = 0; j < len; j++) {if (i & bin[j])c++;}for (j = 0; j < len; j++) {if (!(i & bin[j]))ans[i | bin[j]] += ans[i] / (len - c);}for (j = 0; j < n; j++) {if (f[i] & bin[j])res += ans[i];}}printf("%.10f\n", res / n);return 0;}
著作權聲明:本文部落格原創文章。部落格,未經同意,不得轉載。
CodeForces 482C Game with Strings