本题是一个简化的01背包的问题
解决动态规划的问题的步骤大致可以分为三种:
一,理解dp的含义
二,推理出递推公式
三,找出初始值。
下面来分析这一道题目:
一,理解dp的含义:在这里设成dp[i],意思是当经费为 i 时最小的失败的概率
二,推理出递推公式:先把递推公式给出 dp[j] = min(dp[j],dp[j - w[i] ] * p[i]);下面来分析一下这个公式,dp[j] 是在 不拿第 i 个学校 和 拿了第 i 个学校之间作比较。如果不拿第 i 个学校,则依然是dp[j],反之,如果拿了第i个学校,那么这个就是在 经费为 j - w[i]时的时候的最小的失败的概率上 乘以这个学校失败的概率(当然是要在经费充足的情况下才可以),之后二者在相互比较,取其最小值即可。
三,本题之后定义初始值全部为 1 ,因为如果不选任何一个学校的失败的概率为 1.
看到这里,读者可能还是对这个问题理解不是很清楚,下面通过具体的代码,和草稿来帮助读者理解
#include<iostream>
#include<iomanip>
using namespace std;
#define min(x,y) x<y?x:y
const int MAXN = 10005;
int main()
{
int n,m;
int i ,j ,w[MAXN];
double p[MAXN],dp[MAXN];//记住这里的p数组是失败的概率,dp[i]的意思是在经费为x万元的时候选择该学校失败的概率
while(cin>>m>>n)
{
if(m == 0& n == 0)
break;
//memset(dp,1,sizeof(dp));//全部初始化为1
//cout<<dp[1]<<endl;
for(i =0;i<n;i++)
{
cin>>w[i];
cin>>p[i];
p[i] = 1-p[i];//这里代表的是失败的概率
}
for(i =0;i<=m;i++)
dp[i] = 1;
for(i =0;i<n;i++)
for(j = m;j >= w[i];j--)
{
dp[j] = min(dp[j],dp[j-w[i]]*p[i]);
}
cout<<fixed<<setprecision(1)<<100*(1-dp[m])<<"%"<<endl;
}
}
并从此依次往后类推。