购物(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 ≤ 15
  • 0 ≤ 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';
	}
}
posted @ 2026-07-08 09:45  zhangyirui  阅读(8)  评论(0)    收藏  举报