HDU 1203 I NEED A OFFER!(01背包)

题目地址:点击打开链接

思路:刚开始没想到是01背包,看了别人的解题报告才懂的,算是一道好题吧,和普通背包放东西有点不一样,需要从对立面思考,正面情况太多,求1减去份 也收不到的概率即可

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int cost[10001];
double value[10001],dp[10001];

int main()
{
    int n,m,i,j;
    while(scanf("%d%d",&n,&m))
    {
        memset(dp,0,sizeof(dp));
        if(n + m == 0)
            break;
        for(i=0; i<m; i++)
        {
            scanf("%d%lf",&cost[i],&value[i]);
        }
        for(i=0; i<=n; i++)
        {
            dp[i] = 1.0;
        }
        for(i=0; i<m; i++)
        {
            for(j=n; j>=cost[i]; j--)
            {
                dp[j] = min(dp[j],dp[j-cost[i]] * (1 - value[i]));
            }
        }
        printf("%.1lf%%\n",(1-dp[n])*100);
    }
    return 0;
}

训练赛又练了一遍,发现还是不太熟练,把我写注解的代码贴上来吧

AC代码2:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>

typedef long long ll;
using namespace std;

double dp[10010];

int main()
{
    int n,m,i,j;
    while(scanf("%d%d",&n,&m))
    {
        if(n + m == 0)
            break;
        for(i=0; i<=n; i++)//记得从0开始
        {
            dp[i] = 1.0;
        }
        int cost;
        double value;
        for(i=0; i<m; i++)
        {
            scanf("%d%lf",&cost,&value);
            value = 1.0 - value;
            for(j=n; j>=cost; j--)
            {
                dp[j] = min(dp[j],dp[j-cost] * value);//因为j-cost有可能为0,所以dp得从0开始
            }
        }
        printf("%.1lf%%\n",(1-dp[n])*100);
    }
    return 0;
}



你可能感兴趣的:(HDU 1203 I NEED A OFFER!(01背包))