NYOJ-106背包问题

背包问题

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 3
描述
现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值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
来源
[苗栋栋]原创
上传者

苗栋栋


我的思路(错误的):

按照样例输入的分析的话,输入3个物品,总重量为15,设取第一个物品的重量为x,取第二个物品的重量为y,取第三个物品的和总量为z

x+y+z=15,然后按照我的思路,x*它对应的单位价值+y*它对应的单位价值+z*它对应的单位价值,然后互相博弈,求出最大值,我的代码如下

#include <iostream>
using namespace std;
int main()
{
   int n;
   cin>>n;
   while(n--){
     int s,m,z,b[3300],q=0,sum=0;
     cin>>s>>m;
     int a[s-1][2];
     for(int i=0;i<s;i++){
        cin>>a[i][0];
        cin>>a[i][1];
     }
        for(int i=0;i<=15;i++){
            for(int j=0;j<=15-i;j++){
                z=15-i-j;
               b[q]=a[0][0]*i+a[1][0]*j+a[2][0]*z;
               if(b[q]>sum)
                sum=b[q];
               q++;
            }
        }
        cout<<sum<<endl;
    }

   }
但是输出结果为75,但是样例的结果为65,这个时候我都搞不懂了,为什么呢?

我忽略了一个大问题,就是第一个商品的重量最大为10,第二个商品的重量最大为8,第三个商品的重量最大为9,这个时候,我的思路是不正确的,除了需要保证x+y+z=15以外,还需要保证x<=10,y<=8,z<=9,所以这个时候我知道我的思路是错误的!

然后去网上看了别人的博客,瞬间感觉简单了许多,思路为:
定义结构体,然后对重量进行排序,然后,根据重量的多少进行入库
代码如下:

 
#include <iostream>
#include<algorithm>
using namespace std;
struct wu{
    double v,w;
}a[11];
//对价值进行降序排序
bool cmp(struct wu a,struct wu b){
    return a.v>b.v;
}
int main()
{
   int n;
   cin>>n;
   while(n--){
    int s,m;
    cin>>s>>m;
    for(int i=0;i<s;i++){
        cin>>a[i].v>>a[i].w;
    }
    sort(a,a+s,cmp);
    int sum=0;
   for(int i=0;i<s;i++){
        if(m>=a[i].w){
            sum+=a[i].v*a[i].w;
            m=m-a[i].w;
        }else if(m<a[i].w){
            sum+=m*a[i].v; //重量已满,提前结束
            break;
        }
   }
   cout<<sum<<endl;
   }
}

        

这个时候我看了运行的最优的代码感觉又高大上了不少,但是我现在还没有看懂,回去和室友讨论一下
 
#include<stdio.h>
#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;k<w;k++)
			for(j=m;j>0;j--)
				DP[j]=max(DP[j-1]+v,DP[j]);
		}
		printf("%d\n",DP[m]);
	}
}        




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值