题目106:背包问题

题目链接:

http://acm.nyist.net/JudgeOnline/problem.php?pid=106

描述

现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值v和重量w(1≤v,w≤10);如果给你一个背包它能容纳的重量为m(10≤m≤20),你所要做的就是把物品装到背包里,使背包里的物品的价值总和最大。

输入

第一行输入一个正整数n(1≤n≤5),表示有n组测试数据;
随后有n测试数据,每组测试数据的第一行有两个正整数s,m(1≤s≤10);s表示有s个物品。接下来的s行每行有两个正整数v,w。

输出

输出每组测试数据中背包内的物品的价值和,每次输出占一行。

样例输入

1
3 15
5 10
2 8
3 9

样例输出

65

算法思想:

由于物品可以切分,故是典型的贪心算法。可以将物品按单价进行从大到小进行排序预处理,然后每次选择当前单价最高的物品来装袋,更新袋子的容纳量和价值。最后当袋子的容纳量为0时,输出价值。

最优代码使用了动态规划,每次判断当前物品的单位重量放与不放入袋子中,如果放入袋中是最佳选择,则当前物品重量减1,且袋子容量减1,价值加上该物品的单价。一次类推。DP数组用来存放最优价值。比如DP[i]表示容量为i时,能装下的最大价值。

源代码

#include 
#include 
using namespace std;
struct GOODS{
    int v;
    int w;
};
int larger_cmp(const GOODS &x,const  GOODS &y)
{
    if (x.v > y.v)
        return 1;
    else
        return 0;
}
int main()
{
    int n, s, m, ans;
    cin >> n;
    while (n--)
    {
        ans = 0;
        cin >> s >> m;
        GOODS *pgoods = new GOODS[m];
        for (int i = 0; i < s; i++)
        {
            cin >> pgoods[i].v >> pgoods[i].w;
        }
        //将物品按单价从小到大进行排序
        sort(pgoods,pgoods + s,larger_cmp);
        for (int i = 0; i < s; i++)
        {
            if (m > pgoods[i].w)
            {
                ans += pgoods[i].v * pgoods[i].w;
                m -= pgoods[i].w;
            }
            else
            {
                ans += pgoods[i].v * m;
                break;
            }
        }
        cout << ans << endl;
    }
    return 0;

}

最优源代码

#include
#define max(a,b) a>b?a:b
int main()
{
    int n,s,m,v,w,i,j,k;
    scanf("%d",&n);
    while(n--)
    {
        int DP[25]={0};
        scanf("%d %d",&s,&m);
        for(i=0;i<s;i++)
        {
            scanf("%d %d",&v,&w);
            for(k=0;kfor(j=m;j>0;j--)
            DP[j]=max(DP[j-1]+v,DP[j]);
        }
            printf("%d\n",DP[m]);
        }
    }
}

算法复杂度:

由源代码可知,第一种算法时间复杂度为O(nlogn),因为排序的时间复杂度为O(nlogn),第二种算法的时间复杂度为O(w * max(m))。

你可能感兴趣的:(贪心算法,算法,C++)