01背包的变形问题:以银行的总钱数为背包容量,概率作为价值求解
dp[i][j]表示从前i家银行偷得j元的不被抓的概率,转移方程为
采用滚动数组的做法 dp[i]表示得到i元钱的最大逃跑概率
dp[i][j]表示从前i家银行偷得j元的不被抓的概率,转移方程为
dp[i][j] = max(dp[i][j], dp[i-1][j-m[i]]*(1-p[i]));
#include <cstdio>
#include <algorithm>
using namespace std;
double limit_p, p[110], dp[110][10010];
int t, n, m[110];
int main()
{
scanf("%d", &t);
while(t--)
{
int sum = 0;
scanf("%lf %d", &limit_p, &n);
for(int i=1; i<=n; i++)
{
scanf("%d %lf", &m[i], &p[i]);
sum += m[i];
}
for(int i=0; i<=n; i++)
for(int j=0; j<=sum; j++)
dp[i][j] = 0;
for(int i=0; i<=n; i++)
dp[i][0] = 1;
for(int i=1; i<=n; i++)
for(int j=1; j<=sum; j++)
{
dp[i][j] = dp[i-1][j];
if(j >= m[i])
dp[i][j] = max(dp[i][j], dp[i-1][j-m[i]]*(1-p[i]));
}
for(int i=sum; i>=0; i--)
if(dp[n][i] > (1-limit_p))
{
printf("%d\n", i);
break;
}
}
return 0;
}
采用滚动数组的做法 dp[i]表示得到i元钱的最大逃跑概率
#include <cstdio>
#include <algorithm>
using namespace std;
double dp[10010], p[110], limit_p;
int t, n, sum, m[110];
int main()
{
scanf("%d", &t);
while(t--)
{
sum = 0;
scanf("%lf %d", &limit_p, &n);
for(int i=1; i<=n; i++)
{
scanf("%d %lf", &m[i], &p[i]);
sum += m[i];
}
for(int i=1; i<=sum; i++)
dp[i] = 0;
dp[0] = 1;
for(int i=1; i<=n; i++)
for(int j=sum; j>=m[i]; j--) //必须逆序枚举
dp[j] = max(dp[j], dp[j-m[i]]*(1-p[i]));
for(int i=sum; i>=0; i--)
if(dp[i] > (1-limit_p))
{
printf("%d\n", i);
break;
}
}
return 0;
}