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;
}
posted @ 2013-02-05 23:04  kedebug  阅读(291)  评论(0编辑  收藏  举报