5G云计算网小程序:线上综合服务电子商城

26. 删除有序数组中的重复项

  返回  

DP完全背包问题--货币系统(NOIP2018)

2021/7/20 16:14:53 浏览:

完全背包问题


状态表示

f[i][j] 表示总体积不超过 j 的第 i 个物品的选法

v 是体积,k 是第 i 个物品的数量,w 是价值


状态计算

f[i][j] = max(f[i-1][j], f[i-1][j-v]+w, f[i-1][j-2v]+2w…f[i-1][j-kv]+kw)

f[i][j-v] = max( f[i-1][j-v], f[i-1][j-2v]+w …f[i-1][j-kv]+(k-1)w)

可推 f[i][j] = max(f[i-1][j], f[i][j - v] + w)

//表示物品种类数,m是总容积,v是每类物品的体积
for (int i = 0; i < n; i ++)
	for (int j = 0; j <= m; j ++){
		f[i][j] = f[i - 1][j];
		if (j >= v[i]) 
			f[i][j] = max(f[i][j], f[i][j - v[i]];
	}

cout << f[n][m];

进而可优化为一维写法

for (int i = 0; i < n; i ++)
	for (int j = v[i]; j <= m; j ++)
		f[j] = max(f[j], f[j - v[i]];
cout << f[m];



货币系统


给定集合,求最优解中元素的数量
如集合 3 9 10 16
9 可以被 3 表示,可以去除
16 可以被 3 和 10 表示,可以去除
最后剩下 3 和 10 位最优解
表示只能加,不能进行减法等

输入:
共T组测试数据
第一行输入T,接下来每组数据输入数量和元素

数据范围
0 < T <= 20
1 <= n <= 100
0 <= (集合中数字大小) <= 25000


思路

对于原集合 a
最优解 b1, b2, … bm 一定都是从 a1, a2, … an 中选择的

反证:
 若 bi 不是从 a 中选择的
 bi 可以由 a 中元素表示,而这些元素又可以由最优解 b 中元素表示
 则 bi 可以由 b 中的元素表示,与最优解条件不符

故可以将原集合从小到大排序

对于每个元素,用完全背包求方案数,若为 0,则保留,否则删去


Code

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 110, M = 25010;
int f[M];
int a[N], T, n;

int main(){
    cin >> T;
    
    while (T --){
        cin >> n;
        memset(f, 0, sizeof f);
        
        for (int i = 0; i < n; i ++)
            cin >> a[i];
        
        sort(a, a + n);
        f[0] = 1;
        int res = 0;	//最优解元素数量
        
        //完全背包
        for (int i = 0; i < n; i ++){
            if (f[a[i]] == 0) res ++;	//若没有方案可以表示a[i],最优解元素加1
            for (int j = a[i]; j <= a[n - 1]; j ++)
                f[j] += f[j - a[i]];
        }
        cout << res << endl;
    }
    
    return 0;
}

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号