這題囧了,看完了題目和範例,非常興奮的寫了個0-1背包上去,發現WA了,後來仔細想想不對,要求的是最大的安全係數(暫且這麼認為 - -),這樣定義的方程最有比較大的變化。
做如下定義:
//定義dp[i]為搶了i元錢的最大安全係數,<br />//注意初始化的時候dp[0]=1,其他的設定成沒有訪問過<br />//這裡為了好轉移,我將除了dp[0]之外的dp元素置為-1<br />//轉移很好想,就是如下這個方程:<br />for(int i=0;i<n;i++){<br />for(int j=max_money;j>=w[i];j--){<br />if(dp[j-w[i]]!=-1){<br />dp[j]=max(dp[j],dp[j-w[i]]*p[i];<br />}<br />}<br />}<br />//注意p[i]表示的安全係數,這樣資料中輸入的並不是,所以要記得轉化<br />
這樣用O(n^2)的時間複雜度就可以搞定這道dp題。
我的完整代碼:
#include <cstdio><br />#include <cstring><br />#include <cstdlib><br />#include <algorithm><br />using namespace std;<br />const int MAX=11000;<br />double dp[MAX];<br />int vol;<br />struct Node{<br />int w;<br />double p;<br />}node[120];<br />int main(){<br />int t,n;<br />double p;<br />scanf("%d",&t);<br />while(t--){<br />scanf("%lf%d",&p,&n);<br />p=1-p;<br />vol=0;<br />for(int i=0;i<n;i++){<br />scanf("%d%lf",&node[i].w,&node[i].p);<br />vol+=node[i].w;<br />node[i].p=1-node[i].p;<br />}<br />for(int i=0;i<=vol;i++){<br />dp[i]=-1;<br />}<br />dp[0]=1;<br />for(int i=0;i<n;i++){<br />for(int j=vol;j>=node[i].w;j--){<br />if(dp[j-node[i].w]!=-1&&dp[j]<dp[j-node[i].w]*node[i].p){<br />dp[j]=dp[j-node[i].w]*node[i].p;<br />}<br />}<br />}<br />for(int i=vol;i>=0;i--){<br />if(dp[i]>=p){<br />vol=i;<br />break;<br />}<br />}<br />printf("%d/n",vol);<br />}<br />return 0;<br />}<br />