题意:给出银行的个数和被抓概率上限P。在给出每个银行的钱和抢劫这个银行被抓的概率。 求不超过被抓概率上线能抢劫到最多的钱。 两种方法 方法一:dp[j]为抢劫了j元钱不被抓到概率,状态转移方程dp[j] = max(dp[j], dp[j - w[i]] * p[i])#include <iostream> #include <set> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <map> using namespace std; const int maxn = 10010; double dp[maxn]; double p[maxn]; int w[maxn]; int main() { //freopen("in.txt", "r", stdin); int T; int cas = 0; scanf("%d", &T); while(T--) { int sum = 0; double P; int n; scanf("%lf%d", &P, &n); for(int i = 1; i <= n; i++) { scanf("%d%lf", &w[i], &p[i]); p[i] = 1.0-p[i]; sum += w[i]; } for (int i = 0; i <= sum; i++) { dp[i] = 0; } dp[0] = 1.0; //没有枪钱那么不被抓的概率就是1 for(int i = 1; i <= n; i++) { for(int j = sum; j >= w[i]; j--) { if (dp[j - w[i]]) { //当dp[j - w[i]>0才有比较的必要,不然dp[j - w[i]] * p[i]=0,这样做更加省时。 dp[j] = max(dp[j], dp[j - w[i]] * p[i]); } } } for(int i = sum; i >= 0; i--) { if(1-dp[i] <= P) { printf("Case %d: %d\n", ++cas, i); break; } } } return 0; }
方法二:dp[i][j]表示前 i 个银行抢劫到 j 这么多钱被抓的概率。
转移方程 dp[i][j] = min(dp[i-1][j] , dp[i-1][j-v[i]])
#include<cstdio> #include<algorithm> using namespace std; double d[111][11100]; int main(){ int t,n,x[111]; double p,y[111]; scanf("%d",&t); for(int cse=1; cse<=t; ++cse){ scanf("%lf%d",&p,&n); int sum=0; for(int i=1; i<=n; ++i){ scanf("%d%lf",x+i,y+i); sum+=x[i]; } for(int i=0; i<=n; ++i){ for(int j=0; j<=sum; ++j) d[i][j]=1; } d[0][0]=0; for(int i=1; i<=n; ++i){ for(int j=0; j<=sum; ++j){ if(j>=x[i]) d[i][j]=min(d[i-1][j],d[i-1][j-x[i]]+(1-d[i-1][j-x[i]])*y[i]); else d[i][j]=d[i-1][j]; } } for(int i=sum; i>=0; --i){ if(d[n][i]<p){ printf("Case %d: %d\n",cse,i); break; } } } return 0; }
LightOJ1079 Just another Robbery 01背包、概率
最新推荐文章于 2021-10-21 11:11:21 发布