1. 程式人生 > >TYVJ.1864.[Poetize I]守衛者的挑戰(概率DP)

TYVJ.1864.[Poetize I]守衛者的挑戰(概率DP)

四舍五入 打開 can () ret 鏈接 容量 scanf int

題目鏈接...無
題目:

P1864 [Poetize I]守衛者的挑戰

時間: 1000ms / 空間: 131072KiB / Java類名: Main

描述

  打開了黑魔法師Vani的大門,隊員們在迷宮般的路上漫無目的地搜尋著關押applepi的監獄的所在地。突然,眼前一道亮光閃過。 “我,Nizem,是黑魔法聖殿的守衛者。如果你能通過我的挑戰,那麽你可以帶走黑魔法聖殿的地圖……”瞬間,隊員們被傳送到了一個擂臺上,最初身邊有一 個容量為K的包包。
  擂臺賽一共有N項挑戰,各項挑戰依次進行。第i項挑戰有一個屬性ai,如果ai>=0,表示這次挑戰成功後可以再獲 得一個容量為ai的包包;如果ai=-1,則表示這次挑戰成功後可以得到一個大小為1 的地圖殘片。地圖殘片必須裝在包包裏才能帶出擂臺,包包沒有必要全 部裝滿,但是隊員們必須把 【獲得的所有的】地圖殘片都帶走(沒有得到的不用考慮,只需要完成所有N項挑戰後背包容量足夠容納地圖殘片即可),才能拼出完 整的地圖。並且他們至少要挑戰成功L次才能離開擂臺。

  隊員們一籌莫展之時,善良的守衛者Nizem幫忙預估出了每項挑戰成功的概率,其中第i項挑戰成功的概率為pi%。現在,請你幫忙預測一下,隊員們能夠帶上他們獲得的地圖殘片離開擂臺的概率。

輸入格式

  第一行三個整數N,L,K。
  第二行N個實數,第i個實數pi表示第i項挑戰成功的百分比。
  第三行N個整數,第i個整數ai表示第i項挑戰的屬性值.

輸出格式

  一個整數,表示所求概率,四舍五入保留6 位小數。

輸入

樣例輸入1

3 1 0
10 20 30
-1 -1 2

樣例輸入2

5 1 2
36 44 13 83 63
-1 2 -1 2 1

輸出

樣例輸出1

0.300000

樣例輸出2

0.980387

備註

  若第三項挑戰成功,如果前兩場中某場勝利,隊員們就有空間來容納得到的地圖殘片,如果挑戰失敗,根本就沒有獲得地圖殘片,不用考慮是否能裝下;若第三 項挑戰失敗,如果前兩場有勝利,沒有包來裝地圖殘片,如果前兩場都失敗,不滿足至少挑戰成功次()的要求。因此所求概率就是第三場挑戰獲勝的概率。
  對於 100% 的數據,保證0<=K<=2000,0<=N<=200,-1<=ai<=1000,0<=L<=N,0<=pi<=100。

/*
答案與勝利場數、當前剩余容量(容量-碎片數)有關,所以設f[i][j][k]表示前i關中,勝了j場,容量為k的概率 
如果勝利,f[i][j][k] -> f[i+1][j+1][Turn(k+a[i])] (Turn表示對應的偏移)
失敗,f[i][j][k] -> f[i+1][j][k] 用刷表法,f[i+1][j+1][Turn(k+a[i+1])] += f[i][j][Turn(k)] f[i+1][j][Turn(k)] += f[i][j][Turn(k)] 最後只需統計 ∑f[n][j][k] (j>=勝利關數 , k>=0) (k很大,n比較小,但實際>n的部分(容量大了)就毫無意義,所以>n直接設為n即可) (容量-碎片數可能為負,因為只要最後n關後能帶出去就成立,中間會有放不下但最後能放下的情況。 所以負數為下標是可行的,要偏移) */ #include<cstdio> #include<cctype> using namespace std; const int N=204; int n,l,k,a[N]; double f[N][N][N<<1],p[N]; inline int read() { int now=0,f=1;register char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);now=now*10+c-'0',c=getchar()); return now*f; } inline int Turn(int x) { if(x>n) x=n; return x+201; } int main() { n=read(),l=read(),k=read(); for(int i=1;i<=n;++i) scanf("%lf",&p[i]),p[i]/=100.0; for(int i=1;i<=n;++i) a[i]=read(); f[0][0][Turn(k)]=1.0; for(int i=0;i<n;++i) for(int j=0;j<=i;++j)//勝場 for(int k=-i;k<=n;++k)//當前容量的所有可能 f[i+1][j+1][Turn(k+a[i+1])]+=f[i][j][Turn(k)]*p[i+1], f[i+1][j][Turn(k)]+=f[i][j][Turn(k)]*(1.0-p[i+1]); double res=0.0; for(int i=l;i<=n;++i)//勝場數滿足 for(int j=0;j<=n;++j)//背包容量>=0,即能帶走所有碎片 res+=f[n][i][Turn(j)]; printf("%.6lf",res); return 0; }

TYVJ.1864.[Poetize I]守衛者的挑戰(概率DP)