首页 > 其他分享 >DP(分组背包两种二进制优化) Problem S:Coins(HDU 2844)

DP(分组背包两种二进制优化) Problem S:Coins(HDU 2844)

时间:2023-03-25 13:36:27浏览次数:40  
标签:... HDU int 2844 Coins 二进制 A3 102 --


Problem S

Time Limit : 2000/1000ms (Java/Other)   Memory Limit :32768/32768K (Java/Other)

Total Submission(s) : 12   Accepted Submission(s) : 0

Problem Description

Whuacmers use coins.They havecoins of value A1,A2,A3...An Silverland dollar. One day Hibix opened purse andfound there were some coins. He decided to buy a very nice watch in a nearbyshop. He wanted to pay the exact price(without change) and he known the pricewould not more than m.But he didn't know the exact price of thewatch.<br><br>You are to write a program which readsn,m,A1,A2,A3...An and C1,C2,C3...Cn corresponding to the number of Tony's coinsof value A1,A2,A3...An then calculate how many prices(form 1 to m) Tony can payuse these coins.

 

 

Input

The input contains severaltest cases. The first line of each test case contains two integers n(1 ≤ n ≤100),m(m ≤ 100000).The second line contains 2n integers, denotingA1,A2,A3...An,C1,C2,C3...Cn (1 ≤ Ai ≤ 100000,1 ≤ Ci ≤ 1000). The last test caseis followed by two zeros.

 

 

Output

For each test case output theanswer 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

算法分析:

更好做法:点击打开链接

一道水题,分组背包思想,第一次普通算法超时,然后用了二进制优化,依旧超时,真是无语,上网重新学习了一篇二进制解法

//朴素算法
#include <bits/stdc++.h>

using namespace std;

int main()

{

   int n,m;

   while(scanf("%d%d",&n,&m)&&(n||m))

    {

       int i,j,k,a[102],c[102],f[100002];

       for(i=1;i<=n;i++)

           scanf("%d",&a[i]);

       for(i=1;i<=n;i++)

           scanf("%d",&c[i]);

         for(i=0;i<100002;i++)

           f[i]=0;

 

         for(i=1;i<=n;i++)

         for(j=m;j>=0;j--)

         for(k=0;k<=c[i];k++)

         if(j>=k*a[i])

           f[j]=max(f[j],f[j-k*a[i]]+k*a[i]);

           int ans=0;

           for(i=1;i<=m;i++)

           {

                if(f[i]==i])  ans++;

           }

           printf("%d\n",ans);

    }

   return 0;

}

 

 

 

 

//这种二进制超时
#include <bits/stdc++.h>

using namespace std;

int main()

{

   int n,m;

   while(~scanf("%d%d",&n,&m)&&(n||m))

    {

       int a[102],c[102],f[100002],v[100002];

       for(int i=0;i<n;i++)

           scanf("%d",&a[i]);

       for(int i=0;i<n;i++)

           scanf("%d",&c[i]);

 

 

           //二进制优化

 

           int j=0;

          for(int i=0;i<n;i++)

          {

               int t=1;

               while(c[i]>=t)

               {

                   j++;

 

                   v[j]=a[i]*t;

                   c[i]-=t;

                  t*=2;

               }

               j++;

               v[j]=c[i]*a[i];//将c[i]以2为指数的堆:1,2,4.....2的(k-1)次方,c[i]-(2的k次方)+1

          }

        for(int i=0;i<100002;i++)

           f[i]=0;

           for(int i=0;i<j;i++)

                for(int k=m;k>=v[i];k--)

                f[k]=max(f[k],f[k-v[i]]+v[i]);

 

           int ans=0;

           for(int i=1;i<=m;i++)

           if(f[i]==i)  ans++;

           printf("%d\n",ans);

    }

   return 0;

}

 

//这种二进制优化过了
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)&&(n||m))
    {
        int i,j,k,p,a[105],c[105],f[100005];
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(i=1;i<=n;i++)
            scanf("%d",&c[i]);

          memset(f,0,sizeof(f));
          f[0]=1;//初始化
          for(i=1;i<=n;i++)
          {
              k=1;
              while(c[i]>=k)//二进制优化
              {
                  p=k*a[i];
                  for(j=m;j>=p;j--)
                    if(f[j-p]==1)
                    f[j]=1;
                   c[i]-=k;
                   k*=2;
              }
              if(c[i])
              {
                p=a[i]*c[i];
                for(j=m;j>=p;j--)
                    if(f[j-p]==1)
                    f[j]=1;
              }
          }
            int ans=0;
            for(i=1;i<=m;i++)
            {
                if(f[i]==1)  ans++;
            }
            printf("%d\n",ans);
    }
    return 0;
}

 

标签:...,HDU,int,2844,Coins,二进制,A3,102,--
From: https://blog.51cto.com/u_14932227/6149354

相关文章

  • DP Problem Q:Piggy-Bank(HDU 1114)
    ProblemQTimeLimit:2000/1000ms(Java/Other)   MemoryLimit:65536/32768K(Java/Other)TotalSubmission(s):2   AcceptedSubmission(s):1ProblemDescr......
  • DP Problem R:Big Event in HDU(HDU 1171)
    ProblemRTimeLimit:10000/5000ms(Java/Other)   MemoryLimit:65536/32768K(Java/Other)TotalSubmission(s):1   AcceptedSubmission(s):0ProblemDesc......
  • DP Problem P:Bone Collector(HDU 2602
    ProblemPTimeLimit:2000/1000ms(Java/Other)   MemoryLimit:32768/32768K(Java/Other)TotalSubmission(s):1   AcceptedSubmission(s):1ProblemDescr......
  • 排序01背包 Problem W:Proud Merchants(HDU 3466)
    ProblemWTimeLimit:2000/1000ms(Java/Other)   MemoryLimit:131072/65536K(Java/Other)TotalSubmission(s):2   AcceptedSubmission(s):1ProblemDesc......
  • 【hdu6547】Tree(树链剖分, 线段树区间根号)
    problemalgorihtm1、树链剖分什么是树链剖分(重链剖分)?树链,就是树上的路径。剖分,就是把路径分类为重链和轻链。对于树上的一个点,与其相连的边中,连向的节点子树大小最大(重儿子)......
  • hdu 1853 Cyclic Tour(费用流OR二分图最佳匹配,5级)
    O- CyclicTourTimeLimit:1000MS     MemoryLimit:65535KB     64bitIOFormat:%I64d&%I64uSubmit StatusSystemCrawler (2013-05-30)......
  • A strange lift HDU - 1548 (BFS)
    题意:第i个火车站都有一个数字Ki(0≤Ki≤N),火车在第i站只能前进Ki站或后退Ki站。火车只能在第1站和第N站之间行驶。请问,从第a站到第b站最少需前进或后退......
  • How Many Tables HDU - 1213(并查集/连通块数量)
    题意:朋友的朋友是朋友如果A认识B,B认识C,那么ABC三个人就可以坐在同一张桌子上但如果A认识B,C认识D,那我们就默认AB和CD不认识,需要准备两张桌子现在我们需要你计算出,我们一......
  • Red and Black HDU - 1312 (连通块的大小)
    题意:求某点所在连通块的大小。分析:由某点进行dfs,每次标记该点,并计数。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;constintN=110,INF=......
  • 变形课 HDU - 1181 (dfs)
    题意:给定多个单词,每个单词的首字母可以到末字母,问能否由'b'到'm'。分析:将每个单词首尾字母建图,dfs('b')将能到的所有字母进行标记,最后检查'm'是否被标记。#include......