アルゴリズム-コイン交換(コインの最小数)

 タイトルの説明

異なる金種の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;
}

アイデア

  • 動的プログラミングアルゴリズムを使用
  • この質問の詳細なアイデアは、後続のバージョンで提供されます。

おすすめのトピック

  1.  アルゴリズム-ロボットによるコイン収集(コイン収集問題)
  2. アルゴリズム-コイン行の問題

 それがあなたを助けるなら、それを好きになることを忘れないでください!

公開された18元の記事 ウォンの賞賛224 ・は 10000 +を見て

おすすめ

転載: blog.csdn.net/qq_45703420/article/details/105441140