4648. 【noip2016提高a組模擬7.17】錦標賽
problem
n
nn個人進行n−1
n-1n−
1輪淘汰賽。已知i
ii戰勝j
jj勝率為ai,
ja_
ai,j
,求乙個排列使得1
11獲勝概率最大.
n ≤18
n\le 18
n≤18
solution
首先考慮乙個暴力做法:如果已經知道了排列,怎麼計算1
11獲勝的概率。
我們令fk,
if_
fk,i
表示在進行到第k
kk輪時,i
ii為擂主的概率。
那麼如果知道了排列順序d
dd,則可以直接按照下面這個方式進行dp:
f[1]
[d[1]]
=1;f
(i,2
, n)
f(j,
1, n)
if(d[i]
^ j)
這樣子會發現n=10
n=10
n=10
時剛好被卡,然後這時有乙個顯然的結論:
1如果想要贏得概率最大,必須要最後乙個出場證明是幾乎顯然的,我們可以很容易的通過調整法反證。
於是搜尋 + 簡單的dp可以得到30分的不錯分數。
並且通過這個性質,我們容易想到乙個貪心的做法:
通過贏1
11概率越大的放的越前,並且在此之後對排列進行調整,具體是每次列舉兩個人,看如果交換它們後,1
11贏得概率的是否變大,如果變大就進行調整。這樣進行若干次之後,必定某一時刻會達到最優排列。
這種調整 + 貪心的思想可以拿到100分的不錯分數,並且時間複雜度十分優秀。
#include
#define f(i, a, b) for (int i = a; i <= b; i ++)
#define mem(a, b) memset(a, b, sizeof a)
const
int n =20;
using namespace std;
int n, d[n]
; bool vis[n]
;double a[n]
[n], ans, f[n]
[n];
double
doit()
return f[n][1
];}int
main()
printf
("%.7lf\n"
,doit()
);}
事實上,這題顯然是一道狀壓dp的題目。
但我們發現無論怎麼樣狀壓,正著推需要進行取max和累加兩種操作,顯然是不行的。
那麼嘗試著從最終的結果往回推,發現問題就變得簡單了許多。
因為任何乙個局面(我們用狀態s
ss代替),最終的結果一定都是1
11贏,那不妨列舉一下當前這個局面下誰第乙個出場,以及第乙個出場的人與誰進行pk,並轉移到當前狀態。
那麼我們就讓fi,
jf_
fi,j
表示當前局面為i
ii的情況下,j
jj第乙個出場,1
11最後贏的概率。
每次則列舉乙個與j
jj進行決鬥的人k
kk,然後通過這樣的轉移來進行:
f [i
][j]
=max
f[i][j] = max\
f[i][j
]=ma
x
#include
#define f(i, a, b) for (int i = a; i <= b; i ++)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define mx(a, b) ((a) = max(a, b))
#define mem(a, b) memset(a, b, sizeof a)
const
int n =
19, m =
262200
;using namespace std;
int n, d[n]
, shl[n]
;double ans, a[n]
[n], f[m]
[n];
intmain()
f(i,
1, n)
mx(ans, f[shl[n]-1
][i]);
printf
("%.7lf"
, ans)
;}
簡單的期望 狀壓dp
dp定義真的神,直接的想法是 f x maxn 為第 x 個操作,狀態 maxn maxn 1 200,好像沒有暴力分高 實際上我們可以這樣定義 f x maxn len 0 1 表示後八位 maxn 第九位0 1,第九位之後連續長度為 j 概率 為什麼這樣定義 實際上質因數分解後2的次數就是後面0...
bzoj 1076(狀壓dp)(期望dp)
傳送門 題解 dp i j 表示第i輪狀態為j 狀態中為1的位表示當前物品還沒被取走 的最大期望得分。為了防止從無效狀態轉移至有效狀態,採用倒推法,從已知的有效狀態往回推,具體注釋在 中。p.s.不寫memset可以快接近一倍,但是為了思維嚴密性,還是寫乙個,反正都能過 注意 由於吃過的寶物可以再吃...
抽卡 狀壓DP 期望DP 係數遞推
這題的從狀態定義上就有點特別,考場上沒想到怎麼設定狀態來限制1次克金中m次的抽取。只打了m 1的點,沒取模爆0了。加上是20分。我的狀態定義很簡單,但是這個題如果把每個物品拆成三個然後硬轉移狀態數太多,這樣的話一共有27個物品,顯然1e9就死了。那麼考慮為什麼要狀壓,其實是因為不同種物品概率不同,並...