POJ 1252 Euro Efficiency(完全背包变型)

题意:

有 6 种硬币,每一种价格使用最优的策略使所需硬币数最少。问价格 1-100 所需要的平均硬币数以及最大需要的硬币数。

思路:

1. 完全背包的变型,因为涉及到找零,所以有状态转移 : dp[v] = min(dp[v - w[i]] + 1, dp[v + w[i]] + 1)

2. 我们可以采取两步走的方法避免深度搜索,首先利用完全背包求的不找零的情况下,容量 v 的最优策略:dp[v] = min(dp[v], dp[v - w[i]] + 1)

3. 然后在上面的结果下再利用一次完全背包:dp[v] = min(dp[v], dp[v + w[i]] + 1)

4. 数组要记得开大,比如下面的case: 1 95 96 97 98 99 结果应该是:12.29 25,可以想象:dp[48] = 12 * 2,即 (99 - 95) * 12. 上届很大了 : 99 * 12

 

#include <iostream>

#include <algorithm>

using namespace std;



const int maxn = 1500;

const int infs = 0x3ffffff;

int dp[maxn + 1];



int main()

{

    int cases;

    scanf("%d", &cases);

    while (cases--)

    {

        int w[10];

        for (int i = 0; i < 6; ++i)

            scanf("%d", &w[i]);



        dp[0] = 0;

        for (int v = 1; v < maxn; ++v)

            dp[v] = infs;



        for (int i = 0; i < 6; ++i)

            for (int v = w[i]; v < maxn; ++v)

                if (dp[v - w[i]] != infs)

                    dp[v] = min(dp[v], dp[v - w[i]] + 1);



        for (int i = 0; i < 6; ++i)

            for (int v = maxn - w[i] - 1; v >= 0; --v)

                if (dp[v + w[i]] != infs)

                    dp[v] = min(dp[v], dp[v + w[i]] + 1);



        int ave = 0, maxret = 0;

        for (int v = 1; v <= 100; ++v)

        {

            ave += dp[v];

            maxret = max(maxret, dp[v]);

        }



        double ans = ave;

        ans /= 100;

        printf("%.2lf %d\n", ans, maxret);

    }

    return 0;

}

你可能感兴趣的:(poj)