1253: [DP地狱训练]砝码秤重 __数据加强版
时间限制: 1 Sec 内存限制: 64 MB
提交: 610 解决: 270
[提交][状态][讨论版]题目描述
设有n种砝码,第k种砝码有Ck个,每个重量均为Wk,求:用这些砝码能秤出的不同重量的个数,但不包括一个砝码也不用的情况。输入
输入的第一行只有一个数n,表示不同的砝码的种类数. 第2行至第n+1行,每行有两个整数.第k+1行的两个数分别表示第k种砝码的个数和重量.输出
输出中只有一行数据:Total=N。表示用这些砝码能秤出的不同重量数。样例输入
2 2 2 2 3
样例输出
Total=8
提示
对于100%的数据,砝码的种类n满足:1≤n≤100;
对于30%的数据,砝码的总数量C满足:1≤C≤20;
对于100%的数据,砝码的总数量C满足:1≤C≤100;
对于所有的数据,砝码的总重量W满足:1≤W≤400000;
多重背包,把每一种重量的砝码二进制分割,然后设计dp方程表示某种重量是否能秤出。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <vector> 7 8 using namespace std; 9 10 int n, f[500000], c, w, ans; 11 12 vector<int> pack; 13 14 int main(){ 15 scanf("%d", &n); 16 f[0] = 1; 17 for(int i = 1 ; i <= n ; i++){ 18 scanf("%d%d", &c, &w); 19 for(int i = 1 ; i <= c ; i <<= 1){ 20 pack.push_back(i * w); 21 c -= i; 22 } 23 if(c)pack.push_back(c * w); 24 } 25 for(int i = 0 ; i < pack.size() ; i ++){ 26 for(int j = 450000 ; j >= pack[i] ; j --){ 27 f[j] |= f[j - pack[i]]; 28 } 29 } 30 for(int i = 1 ; i <= 450000 ; i ++){ 31 ans += f[i]; 32 } 33 printf("Total=%d\n", ans); 34 }