題目描述:Roy去搶銀行,如何在不被抓住的情況下搶到最多的錢。給出搶每個銀行能搶到的錢和被抓到的機率。
分析:剛開始以為機率只有兩位小數,乘以100直接做的,結果探索資料不是這樣的,果斷wa了。然後一直在這裡糾結,背包容量不為整數怎麼辦。無奈之下看一下別人的解題報告,發現可以讓搶的錢看做背包容量,被抓住的機率為背包價值。(趕腳自己在死學習,o(╯□╰)o)。但是自己又想錯了,直接將每次搶銀行沒被抓住的機率想加,懂點機率的人都知道這是很愚蠢的想法(o(╯□╰)o)。
下面是代碼:
/*Hdu 2955 Robberies DP 0-1背包 轉移方程:f[j] = max{f[j],f[j-v]*p} f[j]表示搶的錢為j時的最大逃跑機率*/#include<iostream>using namespace std;const int maxn = 10005;double p[105],f[maxn],P;int val[105],tot;int N;double Max(double a,double b){ return a > b ? a : b;}int main(){ int t; cin>>t; while(t--) { cin>>P>>N; tot = 0; for(int i = 0; i < N; i++) { cin>>val[i]>>p[i]; tot += val[i]; } for(int i = 1; i <= tot; i++) f[i] = 0; f[0] = 1; for(int i = 0; i < N; i++) { for(int j = tot; j >= val[i]; j--) { f[j] = Max(f[j],f[j-val[i]]*(1-p[i])); } //for(int k = 1; k <= tot; k++) cout<<f[k]<<" "; //cout<<endl; } for(int i = tot; i >= 0; i--) { if(f[i] >= (1 - P)) { //cout<<f[i]<<endl; cout<<i<<endl; break; } } } return 0;}
之前不是很懂用一維數組為啥是按逆序來遞推的,想了半天才想出了一點頭緒。
每次迴圈是用一維數組來儲存資訊,這樣每次都要覆蓋原來的資訊。因此要在該點資訊被覆蓋之前更新和它有關點的資訊。這樣只能逆序迴圈了。這道題就到這裡吧。
但是還是有點收穫的:
一)、在做0-1背包這類題時,選好背包的容量以及物品價值。就像這道題一樣。
二)、物品的價值不光可以相加,也可以相乘。就像這道題一樣。
三)、轉移數組的初始化問題,這也需要注意。不同的題目,初始化也不一樣。
好吧,就是這樣子。:-D