Problem A
Time Limit : 2000/1000ms (Java/Other) Memory Limit :32768/32768K (Java/Other)
Total Submission(s) : 6 Accepted Submission(s) : 2
Problem Description
The aspiring Roy the Robberhas seen a lot of American movies, and knows that the bad guys usually getscaught in the end, often because they become too greedy. He has decided to workin the lucrative business of bank robbery only for a short while, beforeretiring to a comfortable job at auniversity.<br><br><center><imgsrc=../../../data/images/con211-1010-1.jpg></center> <br>For a fewmonths now, Roy has been assessing the security of various banks and the amountof cash they hold. He wants to make a calculated risk, and grab as much moneyas possible.<br><br><br>His mother, Ola, has decided upon atolerable probability of getting caught. She feels that he is safe enough ifthe banks he robs together give a probability less than this.
Input
The first line of input givesT, the number of cases. For each scenario, the first line of input gives afloating point number P, the probability Roy needs to be below, and an integerN, the number of banks he has plans for. Then follow N lines, where line jgives an integer Mj and a floating point number Pj . <br>Bank j containsMj millions, and the probability of getting caught from robbing it is Pj .
Output
For each test case, output aline with the maximum number of millions he can expect to get while theprobability of getting caught is less than the limitset.<br><br>Notes and Constraints<br> 0 < T <=100<br> 0.0 <= P <= 1.0<br> 0 < N <= 100<br> 0< Mj <= 100<br> 0.0 <= Pj <= 1.0<br> A bank goesbankrupt if it is robbed, and you may assume that all probabilities areindependent as the police have very low funds.
Sample Input
3
0.04 3
1 0.02
2 0.03
3 0.05
0.06 3
2 0.03
2 0.03
3 0.05
0.10 3
1 0.03
2 0.02
3 0.05
Sample Output
2
4
6
算法分析:
01背包不能看出,但第一次涉及到概率问题,此题求他被抓到积累不好求,可以从反面去想,计算他成功的概率,把使所有的概率换成1-P(成功概率)。
设f[j]为抢到j现金的成功概率。
动态转移方程:
f[j]=max(f[j],f[j-n[i]]*p[i])
边界条件:
f[0]=1 (什么都不抢)
代码实现:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int i,T,N,n[105],j;
double p[105],P;
cin>>T;
for(int k=1;k<=T;k++)
{
double sum=0,f[10005]={0};
cin>>P>>N;
P=1-P;
for(i=1;i<=N;i++)
{
cin>>n[i]>>p[i];
sum+=n[i]; //计算总共能获得钱数
p[i]=1-p[i]; //换成成功率
}
f[0]=1; //如果什么都不抢,成功率为0
for(i=1;i<=N;i++) //枚举能抢的银行
for(j=sum;j>=n[i];j--) //将总钱数看出背包容量
f[j]=max(f[j],f[j-n[i]]*p[i]);
for(i=sum;i>=0;i--) //求出成功率恰好满足给出的
if(f[i]>=P) break;
cout<<i<<endl;
}
return 0;
}
import java.util.Scanner;
public class Main {
static double [] dp=new double[10005];
static double [] a=new double[105];
static int [] v=new int[105];
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int cas=0;
int T=in.nextInt();
while(T-->0){
cas++;
double p=in.nextDouble();
p=1-p;
int n=in.nextInt();
int sum=0;
for(int i=1;i<=n;i++)
{
v[i]=in.nextInt();
a[i]=in.nextDouble();
a[i]=1-a[i];
sum+=v[i];
}
for(int i=0;i<=sum;i++)
dp[i]=0;
dp[0]=1;
for(int i=1;i<=n;i++)
{
for(int j=sum;j>=v[i];j--){
//System.out.println(sum+" "+(j-v[i]));
dp[j]=Math.max(dp[j], dp[j-v[i]]*a[i]);
}
}
int i;
for(i=sum;i>=0;i--)
{
//System.out.println(i);
if(dp[i]>=p)
{
break;
}
}
System.out.print("Case "+cas+": ");
System.out.print(i);
System.out.println();
}
System.gc();
}
}