最近好像跟背包问题有缘啊,已经做了好几道了。不过感觉这个问题确有它值得研究之处,也从中学到不少东西呵&
这道题目的大意是:有n种材料,每种材料有数量c和长度h还有一个特殊限制(可以看成一个背包的容量)
出题者要你求出用这n种材料可以累加出的最大长度而且其中的每一种材料中的任何一个元素都不能高过这个限制a.想了想,貌似可以用多重背包来形容这个问题,当然我是非专业的,说得不恰当还请大家原谅;
下面的这段代码中有几点值得注意:
首先是这道题中的关键部分和我写的1276题非常相似(参考了网路上大牛的代码 先谢过~)
通过这两个题我发现:这种方法只适用于(这里我们用背包问题的原始定义来形象的说明)物品的重量等于其价值的情况;
非这种情况那就请老老实实按书上的方法做吧(如果说错了 还望您指出,不过我是这样认为的);
这种方法确实很快,而且比课本上提到的dp方法更牛,一定要掌握呵&
其次是这道题一定要先排序,再dp;
为什么呢?我想了想 给出下面一个例子:
如果数据是这样的:
2
7 40 3
5 23 1
如果不排序 那么按照那个算法26是不可及的
但是如果排序(按a从小到大)
变成
5 23 1
7 40 3
那么26就可能了
是不是很神奇?但这就是区别 所以本题必须要排序;
我后来又想了想 发现这其实是一个策略的问题,在实际中,我们也当然会把安全的部分放在底层,这总方法感觉上就更稳妥些,而且也带有某种贪心的性质我觉得。
如果哲学的来理解,我引用一句经典的话:九层之台,起于累土,千里之行,始于足下。呵呵,我感觉还挺符合本题的,不知道您觉得呢?
AC CODE:
#include <iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
struct node
{
int h;
int a;
int c;
}a[401];
int cmp(node a,node b)
{
return a.a<b.a;
}
bool dp[40001];
int main ()
{
int n;
int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].h,&a[i].a,&a[i].c);
}
sort(a+1,a+1+n,cmp);
int max=0;
dp[0]=true;
for(i=1;i<=n;i++)
{
for(k=max;k>=0;k--)
if(dp[k]==true)
{
for(j=1;j<=a[i].c;j++)
{
int temp;
temp=k+j*a[i].h;
if(temp>a[i].a)
break;
dp[temp]=true;
if(temp>max)
max=temp;
}
}
}
printf("%d\n",max);
return 0;
}