Os pães clássicos do algoritmo dp de programação dinâmica compõem o número java

contente

bolos de tópico compõem

ideia de programação dinâmica

código específico


Bolos de tópico  compõem o número

Xiao Ming toma café da manhã em uma loja de pães cozidos no vapor quase todas as manhãs. Ele descobriu que esta loja de pães cozidos no vapor tem NN tipos de vaporizadores, dos quais o iith vaporizador pode conter pães cozidos no vapor A_iAi exatamente. Cada tipo de vaporizador possui um número muito grande de gaiolas, que podem ser consideradas gaiolas infinitas. 

Sempre que um cliente quiser comprar XX pães cozidos no vapor, o tio que vende pães cozidos no vapor selecionará rapidamente várias gaiolas de pães cozidos no vapor, para que haja exatamente XX pães cozidos no vapor nessas gaiolas. Por exemplo, existem 33 tipos de vaporizadores, que podem conter 3, 43, 4 e 55 pães, respectivamente. Quando um cliente quiser comprar 1111 pães, o tio escolherá 22 gaiolas de 33 mais 11 gaiolas de 55 (pode também escolher 11 gaiolas de 33 mais 22 gaiolas de 44). 

Claro, às vezes o tio Baozi não consegue compensar a quantidade que os clientes querem comprar de qualquer maneira. Por exemplo, existem 33 tipos de vaporizadores, que podem conter 4, 54, 5 e 66 pães, respectivamente. E quando o cliente quis comprar 77 pães, o tio não conseguiu. 

Xiao Ming queria saber quantos tipos de números havia que o tio Baozi não conseguia descobrir.

entrar

A primeira linha contém um inteiro N. (1 <= N <= 100)
Cada uma das seguintes N linhas contém um inteiro Ai. (1 <= Ai <= 100) 

2  
4  
5  

saída

 Um número inteiro que representa a resposta. Se houver números infinitos que não podem ser compostos, imprima INF.

6  

ideia de programação dinâmica

Antes de falar sobre a ideia de programação dinâmica, esta questão também usa o problema clássico da teoria dos números Ax+By=C (x, y>0) : se A e B são relativamente primos, então existe um número infinito de C quando a equação não tem solução. Caso contrário, pode haver uma solução. A generalização para a,b,...,n é válida ao mesmo tempo. Você pode usar essa ideia para descobrir se há um número infinito de pães que não podem ser feitos.

Então, nesta questão, você pode usar a1, a2,...an para representar o número de pães que podem ser colocados e encontrar o x, y,....n apropriado para fazer C. Se a equação tiver uma solução, ela pode ser descoberta, caso contrário, não pode ser descoberta. Quanto a encontrar o máximo divisor comum, você pode usar jogando e dividindo.

Então esta questão pode ser semelhante ao problema da mochila , usando um boolean[] dp, e o índice subscrito indica se os pães de índice podem ser compostos . Quando dp[i] significa que i buns podem ser feitos, então j buns + o i-th steamer podem apenas caber em Ai buns: arr[i] também pode ser feito, ou seja, index=( j+arr[i] ) Os pães também podem ser compostos: dp[j + arr[i]] = true; a ideia de programação dinâmica se reflete nisso e, para economizar tempo, os dados dp[] podem ser atualizados enquanto o dados estão sendo inseridos.

código específico

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);
	}
}

Acho que você gosta

Origin blog.csdn.net/qq_52360069/article/details/123720424
Recomendado
Clasificación