HDU2955(Robberies)
程序员文章站
2022-07-07 22:54:10
...
题意
大概意思就是有一个人要去抢银行,然后算好了每个银行有多少钱,抢这个银行的风险是多少。给定银行数目和风险数,问不超过这个风险数下能抢到的最大金额。看起来好像挺简单的不就是01背包嘛,其实也道题也不简单,坑也不少。
思路
错误的思路:最开始我做这道题强行把风险数转为整数当做背包容量,然后再去做01背包,几发WA之后我不得不怀疑自己的思路的正确性。然后我开始怀疑这个浮点数是不是给的位数很多。还有就是这道题的样例给的神他妈恶心。我最开始以为风险数是叠加做加法的,还神TM合上了答案。注意:概率是做乘法,给的样例做加法竟然很巧妙的对上了,T v T~~~
正确思路:由于金额数不是很大,我们可以枚举每一个金额下的不被抓的概率最大,最后倒叙遍历金额,找到不超过给定的风险数,就是最大能抢到的金额。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
struct info{
double p;
int m;
}s[105];
double dp[10005];
void solve(int n,int m,double p)
{
memset(dp,0,sizeof(dp));
dp[0] = 1.0;
for(int i = 1;i <= n;i++){
for(int j = m;j >= s[i].m;j--){ //不被抓的概率
dp[j] = max(dp[j],dp[j-s[i].m]*(1.0-s[i].p));
}
}
for(int i = m;i >= 0;i--){ //倒叙遍历,从金额最大倒叙遍历
if((1.0-dp[i]) <= p){ //被抓的概率不超过给定的风险数
printf("%d\n",i);
break;
}
}
}
int main()
{
int t;
cin>>t;
while(t--){
double p,n;
int sum = 0;
cin >> p >> n;
for(int i = 1;i <= n;i++){
cin >> s[i].m >> s[i].p;
sum += s[i].m; //所有银行的钱数当做背包容量
}
solve(n,sum,p);
}
return 0;
}
愿你走出半生,归来仍是少年~