HDU 1786 Tempter of the Bone again

又是莫名其妙做出来的,不知道怎么证明自己使用的方法,求解!!

 

Problem Description
Ignatius found some bones in an ancient maze, which fascinated him a lot. However, when he picked them up, the maze began to shake, and Ignatius could feel the ground sinking. He realized that the bone was a trap, and he tried desperately to get out of this maze.
Suddenly, Ignatius heard a very very cool voice, and he recognize that it comes from Beelzebub feng5166:“I know that you like bone, and even I know your nick name is wishingbone. Today, I give you a chance to survive: there are N kinds of bones here and the number of each kind bone is enough, their weights are Wi pounds (1<=i<=N), your bag has a volume of M pounds, and I also know that you will spend 3 seconds time when you pick up any one bone. Today, you must fill up your bag as quick as you can, otherwise, the maze is your place of the death!”.
Oh, my god! Can the poor Ignatius survive? Please help him!
Note: You are guarantied that solution always exist for every test case.
 

 

Input
The input consists of multiple test cases. The first line of each test case contains two integers N and M (1 < N < 10; 0 < M < 1000000000), which denote the kinds of the bone and the capacity of the bag respectively. The next line give N integers W1…Wn (1<=wi<=100), which indicate the weights of bones
The input is terminated with two 0's. This test case is not to be processed.
 

 

Output
For each test case, print the minimal time Ignatius will spend when he can survive. One line per case.
 

 

Sample Input
  
  
2 20 1 5 0 0
 

 

Sample Output
  
  
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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值