動的計画法のdpアルゴリズムの古典的なパンがJavaの数を構成します

コンテンツ

トピックバンズは構成します

動的計画法のアイデア

特定のコード


トピック バンズが数を構成します

シャオミンはほぼ毎朝、蒸しパン屋で朝食を食べます。彼は、この蒸し饅頭店にはNN種類の蒸し器があり、そのうちiith蒸し器がA_iAi蒸し饅頭を正確に保持できることを発見しました。各タイプのスチーマーには非常に多くのケージがあり、無限のケージと見なすことができます。 

顧客がXX個の蒸しパンを購入したいときはいつでも、蒸しパンを販売する叔父はすぐにいくつかの蒸しパンのケージを選択するので、これらのケージには正確にXX個の蒸しパンがあります。たとえば、33種類のスチーマーがあり、それぞれ3、43、4、55個のバンズを入れることができます。顧客が1111のパンを購入したい場合、叔父は33の22のケージと55の11のケージを選択します(33の11のケージと44の22のケージを選択することもできます)。 

もちろん、包子おじさんがとにかく顧客が購入したい量を補うことができない場合があります。たとえば、33種類のスチーマーがあり、それぞれ4、54、5、66個のバンズを入れることができます。そして、顧客が77個のパンを購入したいと思ったとき、叔父はそれらを思い付くことができませんでした。 

シャオ・ミンは、包子おじさんが理解できなかった数の種類を知りたがっていました。

入力

最初の行には整数Nが含まれています。(1 <= N <= 100)
次のN行のそれぞれには、整数Aiが含まれています。(1 <= Ai <= 100) 

2  
4  
5  

出力

 答えを表す整数。補うことができない数が無限にある場合は、INFを出力します。

6  

動的計画法のアイデア

動的計画法のアイデアについて話す前に、この質問では古典的な数論Ax + By = C(x、y> 0)の問題も使用します:AとBが互いに素である場合、Cの数は無限になります方程式には解がありません。そうでなければ、解決策があるかもしれません。a、b、...、nへの一般化も同時に成り立ちます。このアイデアを使用して、構成できないパンが無数にあるかどうかを調べることができます。

したがって、この質問では、a1、a2、... anを使用して、置くことができるバンの数を表し、Cを作成するための適切なx、y、....nを見つけることができます。方程式に解がある場合はそれを理解できますが、そうでない場合は理解できません。最大公約数を見つけることに関しては、あなたは投げて分割することを使うことができます。

次に、この質問は、boolean [] dpを使用して、ナップサック問題に似ている可能性があり、下付き文字のインデックスは、インデックスバンを構成できるかどうかを示します。dp [i]がiバンズを構成できることを意味する場合、jバンズ+i番目のスチーマーはAiバンズにぴったり合うことができます。arr[i]も構成できます。つまり、index =(j + arr [i])バンズも構成できます:dp [j + arr [i]] = true;動的計画法のアイデアがこれに反映され、時間を節約するために、dp[]データを更新することができますデータが入力されています。

特定のコード

import java.util.Scanner;

public class _包子凑数 {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();//N种蒸笼
		int yueshu = 0;//最大公约数
		int[] arr = new int[n + 1];//以下N行每行包含一个整数Ai
		boolean[] dp = new boolean[10000];//下标index表示index个包子是否能够凑出
		dp[0] = true;//默认0个包子可以凑出来
		//在录入数据的同时,即可对dp[index]index个包子是否能够凑出来进行更新处理。
		for (int i = 1; i <= n; i++) {
			arr[i] = scanner.nextInt();//录入数据
			/**
			 * 下面if-else语句动态求输入的数据的最大公约数
			 * 求当前第i种蒸笼恰好能放Ai个包子和前一个蒸笼能放的包子个数的最大公约数
			 */
			if (i == 1)
				yueshu = arr[1];
			else
				yueshu = yue(arr[i], yueshu);
			//更新dp[]数组
			for (int j = 0; j < 10000; j++) {
				/**
				 * 如果dp[j],即j个包子能够凑出来,
				 * 那么j个包子+第i种蒸笼恰好能放Ai个包子:arr[i]也能够凑出来
				 * 即index=(j+arr[i])个包子也能够凑出来。
				 */
				if (dp[j])
					dp[j + arr[i]] = true;//向后递推,动态规划的体现
			}
		}
		//当最大公约数!=1  说明Ai不互质,则有无限个包子数凑不出来
		if (yueshu != 1)
			System.out.println("INF");
		else {
			//否则统计个数
			int sum = 0;
			for (int i = 0; i < dp.length; i++) {
				if (!dp[i])
					sum++;
			}
			System.out.println(sum);
		}
	}
	/**
	 * 辗转相除法求a,b两个数的最大公约数
	 * @param a
	 * @param b
	 * @return
	 */
	public static int yue(int a, int b) {
		if (b == 0)
			return a;
		else
			return yue(b, a % b);
	}
}

おすすめ

転載: blog.csdn.net/qq_52360069/article/details/123720424
おすすめ