タイトルリンク:https://acm.zcmu.edu.cn/JudgeOnline/problem.php?id = 1166
トピック
nコイン、額面ai、各タイプは無制限です。次に、使用できるコインの数であるsを指定して、額面の合計がsと正確に等しくなるようにします。コイン数の最小値と最大値を出力します。
アイデア
アイテムを選択してください、数量は無制限です、そしてそれは完全なバックパックです。
dp1 [i]は両方とも、額面がiのコインの数を表します。合計額面をjに等しくするには、現在のa [i]を選択するか、a [i]を選択しないかの2つのオプションがあります。
a [i]が選択されている場合、sa [i]のみが残り、dp1 [ja [i]] == infまたはdp2 [ja [i]] ==-1の場合、前のコインは逆に、ja [i]に収集される数は、dp [ja [i]] + 1です。ここで、1は現在選択されているコインです。dp1、dp2は、それぞれ最小値と最大値を更新できます。
ACコード
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1e4 + 10;
const int inf = 0x3f3f3f3f;
int a[105], dp1[maxn], dp2[maxn];
int main(){
int n, s;
while(~scanf("%d%d", &n, &s)){
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
memset(dp1, inf, sizeof(dp1));
memset(dp2, -1, sizeof(dp2));
dp1[0] = dp2[0] = 0;
for(int i = 1; i <= n; i ++){
for(int j = a[i]; j <= s; j ++){
if(dp1[j - a[i]] != inf)
dp1[j] = min(dp1[j], dp1[j - a[i]] + 1);
if(dp2[j - a[i]] != -1)
dp2[j] = max(dp2[j], dp2[j - a[i]] + 1);
}
}
if(dp1[s] == inf) dp1[s] = -1;
printf("%d %d\n", dp1[s], dp2[s]);
}
return 0;
}