洛谷P2347 砝码称重 [DP补完计划] [背包问题]

  题目传送门

  

题目描述

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),

输入输出格式

输入格式:

 

输入方式:a1 a2 a3 a4 a5 a6

(表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个)

 

输出格式:

 

输出方式:Total=N

(N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)

 

输入输出样例

输入样例#1: 复制
1 1 0 0 0 0
输出样例#1: 复制

  Total=3


  分析:背包问题,多重背包。这里是把多重背包转化为01背包,用到了一种叫二进制拆分的方法,有兴趣可以去网上查下。

 1 //It is made by HolseLee on 12th May 2018
 2 //Luogu.org 2347
 3 #include<bits/stdc++.h>
 4 #define Fi(i,a,b) for(int i=a;i<=b;i++)
 5 #define Fm(i,a,b) for(int i=a;i>=b;i--)
 6 using namespace std;
 7 const int N=4007;
 8 int m[7]={0,1,2,3,5,10,20};
 9 int n[N],c[N],dp[N],tot,ans,k;
10 int main()
11 {
12   ios::sync_with_stdio(false);
13   Fi(i,1,6){cin>>n[i];tot+=n[i]*m[i];}
14   Fi(i,1,6){for(int j=1;j<=n[i];j*=2){
15       c[++k]=m[i]*j;n[i]-=j;}
16     if(n[i])c[++k]=n[i]*m[i];}
17   Fi(i,1,k)Fm(j,tot,c[i])
18     dp[j]=max(dp[j],dp[j-c[i]]+c[i]);
19   Fi(i,1,tot)if(dp[i]==i)ans++;
20   cout<<"Total="<<ans<<endl;return 0;
21 }

猜你喜欢

转载自www.cnblogs.com/cytus/p/9028821.html