购物(shopping)
购物(Shopping)
题意
DD 有 n 种不同面额的硬币,每种硬币数量无限。第 i 种硬币的面额为 a[i]。
现在 DD 要去 m 家超市购物:
- 第 j 家超市需要购买价值为
c[j]的商品; - 第 j 家超市限制只能使用前
l[j]种硬币(即编号 1 到l[j]的硬币,l[j]可以为 0)。
对于每家超市,求最少需要多少枚硬币恰好凑出c[j]元(不需要找零)。如果无法凑出,输出-1。
范围
1 ≤ n ≤ 150 ≤ l[j] ≤ 2- 硬币面额、商品价值均为正整数
样例
输入
6 3
7 10 15 2 3 24
107 3
12 4
24 2
输出
8
2
3
算法思路
问题分析
由于硬币可以无限使用,且限制了可用的硬币种类,就是完全背包问题。
状态定义
设 dp[i][j] 表示:使用前 i 种硬币,凑出 j 元要的最少硬币数。
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
const int M=2e3+10;
const int INF=0x3f3f3f3f;
int n,m;
int a[N],dp[M][N];
int main(){
cin >> n >> m;
for(int i=1;i<=n;i++) cin >> a[i];
memset(dp,INF,sizeof(dp));
for(int i=0;i<=n;i++) dp[i][0]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<=N-10;j++){
dp[i][j]=dp[i-1][j];
if(j>=a[i]){
dp[i][j]=min(dp[i][j],dp[i][j-a[i]]+1);
//不是继承状态就是找最小值并更新
}
}
}
for(int i=1;i<=m;i++){
int c,l;
cin >> c >> l;
if(dp[l][c]==INF) cout << -1 << '\n';
else cout << dp[l][c] << '\n';
}
}

浙公网安备 33010602011771号