Problem Description
The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually gets caught in the end, often because they become too greedy. He has decided to work in the lucrative business of bank robbery only for a short while, before retiring to a comfortable job at a university.For a few months now, Roy has been assessing the security of various banks and the amount of cash they hold. He wants to make a calculated risk, and grab as much money as possible.
His mother, Ola, has decided upon a tolerable probability of getting caught. She feels that he is safe enough if the banks he robs together give a probability less than this.
Input
The first line of input gives T, the number of cases. For each scenario, the first line of input gives a floating point number P, the probability Roy needs to be below, and an integer N, the number of banks he has plans for. Then follow N lines, where line j gives an integer Mj and a floating point number Pj .
Bank j contains Mj millions, and the probability of getting caught from robbing it is Pj .
Output
For each test case, output a line with the maximum number of millions he can expect to get while the probability of getting caught is less than the limit set.
Notes and Constraints
0 < T <= 100
0.0 <= P <= 1.0
0 < N <= 100
0 < Mj <= 100
0.0 <= Pj <= 1.0
A bank goes bankrupt if it is robbed, and you may assume that all probabilities are independent 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
Source
IDI Open 2009
描述:求在不被抓住的情况下,能在银行一共获得最大的金钱。因为自己的英文能力蛇皮怪,所以用翻译软件翻译出来的也是蛇皮,一半理解一半不理解。一开始的最初理解是,在自己最初的概率条件在,去一家银行,那么自己的概率就会减少这一银行的对于概率,当自己的概率为0的时候,就被抓住。一开始没有想到是01背包问题。采用遍历暴搜的办法去考虑每一种情况,从而得到最大的可获得金钱数。
代码为:
#include<stdio.h>
#include<string.h>
#define maxx 1000
#define maxn 101
struct str
{
double a; //概率总和
int b; // 金钱总和
};
struct str num[maxn][maxx];
int sumnum[maxx];
int main()
{
freopen("in.txt","r",stdin);
int t, i;
scanf("%d", &t);
while(t--)
{
double sv, y;
int maxv;
int n, k = 0, g, h, j, x;
scanf("%lf %d", &sv, &n);
for(i = 0; i < n; i++)
{
scanf("%d %lf", &x, &y);
if(y > sv) continue; // 大于能力,找死
num[k][0].a = y; num[k][0].b = x; k++;
}
for(i = 0; i < k; i++) sumnum[i] = 1;
maxv = num[k-1][0].b;
for(i = k-2; i >= 0; i--)
{
g = 1;
for(j = i+1; j < k; j++)
{
for(h = 0; h < sumnum[j]; h++)
{
if( (num[i][0].a + num[j][h].a) <= sv)
{
num[i][g].a = num[i][0].a + num[j][h].a;
num[i][g].b = num[i][0].b + num[j][h].b;
if(num[i][g].b > maxv) maxv = num[i][g].b;
g++;
}
}
}
sumnum[i] = g;
}
printf("%d\n",maxv);
}
fclose(stdin);
return 0;
}
测试数据全部过了,高兴的一批,高高兴兴去提交,结果是Time Limit Exceed然后默默的看自己的代码,看了半天,感觉不能降低时间复杂度了,就知道我应该最初的想法有问题了,果断百度。果然有问题。是01背包问题,并且应该是以金钱作为背包。然后重写代码:
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <string.h>
using namespace std;
int main()
{
freopen("in.txt","r",stdin);
int t, n, inum[5001], i, sum, j;
double sv, dnum[5001], rnum[5001]; //一开始开辟空间不够,错了。
scanf("%d", &t);
while(t--)
{
scanf("%lf%d", &sv, &n);
sum = 0;
for(i = 0; i < n; i++)
{
scanf("%d%lf", &inum[i], &dnum[i]);
sum += inum[i];
}
memset(rnum, 0, sizeof(rnum));
rnum[0] = 1; //一开始没有写这个,一直不对,好久才反应过来
for(i = 0; i < n; i++)
{
for(j = sum; j >= inum[i]; j--)
rnum[j] = max(rnum[j], rnum[j-inum[i]] * (1-dnum[i]));
}
for(i = sum; i >= 0; i--)
if(rnum[i] > 1-sv) break;
printf("%d\n", i);
}
fclose(stdin);
return 0;
}
|