又是莫名其妙做出来的,不知道怎么证明自己使用的方法,求解!!
2 20 1 5 0 0
12//---------------------------------------------题目意思:把包放满至少需要几个东西,每个东西数量足够。
第一感觉就是背包问题。由于容量最高10亿,把这个作为背包就不现实了,但发现物品种类最多9个,而且重量上限只有100,于是考虑从这里入手。但不知怎么回事,草稿打着打着灵感一来用了递归。搞一个函数ans(x,y);返回x的容量从第y件物品开始放最少需要几件,物品先递减排序。
需要得到的结果自然是ans(背包容量,0);
函数里面:
如果这件物品能放满直接返回x除以第y件物品的价值
如果不能且接下去没有物品了返回-1
走到这一步说明不能放满,还有余数,且接下去还有更小的物品,那就得到一个ans(x%value[y],y+1)。
但这样不一定能得到答案啊,比如说12容量的背包,物品价值有5、3,先放了5,还余2,那3就放不了了,但答案就是3的价值放4次啊。
那怎么办呢?本来只考虑5放2次的情况,那我把5放0~2次的情况都考虑遍,取最小值就好了。
最后还有个问题,(10亿-1)的背包里放价值5可放(2亿-1)次,都考虑过来明显不行。
这个就要看接下来那个数了,比如说接下来的数是3,我只要考虑5最多少放(3-1)次即可,为什么呢?当时感觉就这样=。=,说不清楚,就是这里原以为会WA,结果居然AC了。
感觉跟余数什么的有关,求解释!!
#include<iostream>
int N,M,W[10];
int cmp(const void *a,const void *b){
return *(int *)b-*(int *)a;
}
int f_min(int x,int y){
if(x==-1)return y;
return x<y?x:y;
}
void get_W(){
int i;
for(i=0;i<N;i++)
scanf("%d",&W[i]);
qsort(W,N,sizeof(int),cmp);
}
int ans(int bag,int s){
int w=W[s],up;
if(bag%w==0)return bag/w;
if(s==N-1)return -1;
up=bag/w;
int lim=f_min(up,W[s+1]-1),i,min=-1,temp;
for(i=0;i<=lim;i++){
temp=ans(bag%w+i*w,s+1);
if(temp==-1)continue;
min=f_min(min,up-i+temp);
}
return min;
}
int main(){
while(scanf("%d%d",&N,&M)&&(N||M)){
get_W();
printf("%d/n",3*ans(M,0));
}
return 0;
}