http://poj.org/gotoproblem?pid=1252

(1)不是单纯的01背包问题,硬币有去有回(即有正有负),这使得用想买你的解法,上限难以确定,所以我开了dp[10000]的数组,还未得到好的优化和解释;

(2)对比两种写法:

       1)

for(i=1;i<=6;i++)
    for(j=a[i];j<=N;j++)
        dp[j]=min(dp[j], dp[j-a[i]]+1);
for(i=1;i<=6;i++)
    for(j=N-a[i];j>=0;j--)
        dp[j]=min(dp[j], dp[j+a[i]]+1);

       2)

for(i=1;i<=6;i++)
{
    for(j=a[i];j<=N;j++)
        dp[j]=min(dp[j], dp[j-a[i]]+1);
    for(j=N-a[i];j>=0;j--)
        dp[j]=min(dp[j], dp[j+a[i]]+1);    
}

后一种解法是错误的。其实想一想,背包装的都是“正值”,没见过正负混合装的背包,这里所谓的有正有负,其实本质上是两个背包同时起作用的结果,第二个背包的想过直接叠加在第一个上了。

具体代码:

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=10000;
const int Inf=1<<29;
int a[10];
int dp[N+1];
int main()
{
    int i, j, k, t;
    while(scanf("%d", &t)!=EOF)
    {
        while(t--)
        {
            for(i=1;i<=6;i++) scanf("%d", &a[i]);
            for(i=1;i<=N;i++) dp[i]=Inf;
            dp[0]=0;
            for(i=1;i<=6;i++)
                for(j=a[i];j<=N;j++)
                    dp[j]=min(dp[j], dp[j-a[i]]+1);
            for(i=1;i<=6;i++)
                for(j=N-a[i];j>=0;j--)
                    dp[j]=min(dp[j], dp[j+a[i]]+1);
            int sum=0, Max=-1;
            for(i=1;i<=100;i++)
            {
                sum+=dp[i];
                if(Max<dp[i]) Max=dp[i];
            }
            printf("%.2f %d\n", sum/100.0, Max);
        }
    }
    return 0;
}

 

当然,有分别处理两个背包,再由两者组合,查找出最优值,稍微麻烦一些。

具体代码:

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=100000;
const int Inf=1<<29;
int a[10];
int dp[N+1];
int main()
{
    int i, j, k, t;
    while(scanf("%d", &t)!=EOF)
    {
        while(t--)
        {
            for(i=1;i<=6;i++) scanf("%d", &a[i]);
            for(i=1;i<=N;i++) dp[i]=Inf;
            dp[0]=0;
            for(i=1;i<=6;i++)
                for(j=a[i];j<=N;j++)
                    dp[j]=min(dp[j], dp[j-a[i]]+1);
            for(i=1;i<=6;i++)
                for(j=N-a[i];j>=0;j--)
                    dp[j]=min(dp[j], dp[j+a[i]]+1);
            int sum=0, Max=-1;
            for(i=1;i<=100;i++)
            {
                sum+=dp[i];
                if(Max<dp[i]) Max=dp[i];
            }
            printf("%.2f %d\n", sum/100.0, Max);
        }
    }
    return 0;
}