Coins【暑期培训Z题】【多重背包】

        一道用来防AK的题,但是被我们给弄出来了,还是挺可以的。

People in Silverland use coins.They have coins of value A1,A2,A3...An Silverland dollar.One day Tony opened his money-box and found there were some coins.He decided to buy a very nice watch in a nearby shop. He wanted to pay the exact price(without change) and he known the price would not more than m.But he didn't know the exact price of the watch. 
You are to write a program which reads n,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coins of value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can pay use these coins. 
Input
The input contains several test cases. The first line of each test case contains two integers n(1<=n<=100),m(m<=100000).The second line contains 2n integers, denoting A1,A2,A3...An,C1,C2,C3...Cn (1<=Ai<=100000,1<=Ci<=1000). The last test case is followed by two zeros.
Output
For each test case output the answer on a single line.
Sample Input
3 10
1 2 4 2 1 1
2 5
1 4 2 1
0 0
Sample Output
8
4

        这道题就是要我们求在一定范围内,能够用手头上的一定数量的钱构成几种类型的总和,譬如一个一块和一个两块,在三块钱范围内能组成{1}、{1+2}、{2}的组合。

        思路:这道题如果用普通的多重背包,例如这样(就会超时):

for(int i=0; i

{

for(int j=1; j<=coin[i].b; j++)

{

for(int k=m; k>=coin[i].a*j; k--)

{

if(dp[k-coin[i].a] && !dp[k])

{

dp[k]=1;

sum++;

}

}

}

}

既然都说过了会超时,当然也会讲不超时的算法和思路,

    上面我们用了3个for循环O(n^3)的算法当然的T,我们发现第三个for中的

int k=m; k>=coin[i].a*j; k--

会被一遍遍的遍历,那么我们换种方式,假如知道此时取了几次岂不是更好,那么用一个s数组来存储到达这一个值我们所用去的步数就可以了。

利用s[i]与dp[i]同步的方法,记录到达这个值时候的步数,我们仅需要在循环中假如条件:

s[k-coin[i].a]<coin[i].b

即可,但为什么取小于符是因为原式应当为s[k]<=coin[i].b,但由于s[k]为接下来的处理量,所以我们才对它的前一步进行处理。


完整代码:

#include 
#include 
#include 
using namespace std;
int n,m;
struct node
{
    int a,b;        //价值,数量
}coin[105];
int dp[100005];
int s[100005];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)break;
        memset(coin, 0, sizeof(coin));
        memset(dp, 0, sizeof(dp));
        dp[0]=1;
        int sum=0;
        for(int i=0; im)
            {
                coin[j].b=m/coin[j].a;
            }
        }
        for(int i=0; i

你可能感兴趣的:(背包)