タイトルの説明
異なる金種のn個のコインがあり、各コインの金種は配列T [1:n]に格納されています。次に、これらの金種のコインを使ってお金を見つける必要があります。使用できるさまざまな金種のコインの数は、配列Coins [1:n]に格納されます。与えられた1≤n≤10に対して、使用できるさまざまな額面コインのコインの額面配列Tとコイン数配列、および金額m、0≤m≤20001は、お金mの最小コイン数を計算するプログラムです。
入力
最初の行の1つの整数のみがnの値を示し、2番目の行からの各行にはそれぞれT [j]とCoins [j]の2つの数値があります。最後の行は、見つける金額mです。
アウトプット
コインの最小数、解決策がない場合は-1を出力
入力例
3
1 3
2 3
5 3
18
出力例
5
この質問は動的な計画の質問です。長い間、開始方法がわからなかったので、自分の考えに従って問題を解決しました。
- 配列を大きいものから小さいものに並べ替え、高速な並べ替えを使用します。
- 次に、配列で、変更番号mがコインの値より大きいかどうか、および対応するコインが使い切られたかどうかを判断します。
- 上記の条件が満たされている場合、この値を持つコインは変化の1つです。この値からmが引かれて、新しい変化が得られます。
- 上記の操作を繰り返し、最終的にmが0に等しい場合は、コインの最小数を出力します。それ以外の場合は、-1を出力します。
まずコードを見てください:
typedef struct {
int T;
int Coins;
}Mo;
bool cmp(Mo a, Mo b){
return a.T > b.T ;
}
int ChangeMaking(int m, int n, Mo *a){
sort(a,a+n,cmp);
int flag = 0;
for(int i = 0; i < n; i++){
while(a[i].Coins > 0 && m - a[i].T >= 0){
m -= a[i].T ;
flag ++;
a[i].Coins --;
}
}
if(flag != 0 && m == 0) return flag;
else return -1;
}
何か問題はないと思いますよね?それは大きな間違いです。この例を見てください:
変化の数m = 8とすると、1 5、2 4、1 2があります。この例は単純ですが、コインの最小数は2(2 4)であることがわかりますが、上記のアルゴリズムによれば、正解と矛盾する解決策はありません。
したがって、この問題を解決するために、動的プログラミングのアルゴリズムを正直に学びます。
以下は完全なコードです。
コード
#include<iostream>
using namespace std;
int T[11],Coins[11];
int main(){
int n,m;
cin>>n;
for(int i = 1; i <= n; i++){
cin>>T[i]>>Coins[i];
}
cin>>m;
int dp[20001];
for(int i = 1; i < 20001; i++){
dp[i] = 101;
}
for(int i = 1; i <= n; i++){
for(int j = 1; j <= Coins[i] ; j++ ){
for(int k = m; k >= T[i]; k --){
dp[k]=min(dp[k-T[i]] + 1,dp[k]);
}
}
}
if(dp[m] == 101) cout<<"-1"<<endl;
else cout<<dp[m]<<endl;
return 0;
}
アイデア
- 動的プログラミングアルゴリズムを使用。
- この質問の詳細なアイデアは、後続のバージョンで提供されます。
おすすめのトピック
それがあなたを助けるなら、それを好きになることを忘れないでください!