コンテンツ
1.例
トピックの説明
n個の要素の部分文字列Sが与えられた場合、最大の積を持つ連続した部分文字列を見つける必要があります。
この最大の積が正でない場合は、0(解がないことを示す)を出力する必要があります。
入力
最初の行は整数n(1 <= n <= 18)です。
2行目はn個の整数です。ここで、各整数は[-10,10]の範囲にあります。
出力
整数を含む行を出力し、最大の積を出力します。
テストデータ
コードを参照してください。
2.思考分析
基本的な考え方
このトピックはナップサック問題に似ており、その基本的な考え方は動的計画法で使用できます。解決されたサブ問題の解決策を覚えておいてください。解く、つまりデータをトラバースするときに、トラバーサルプロセス中に取得された最大積が記録され、トラバースが続行されます。各トラバースを通じて、最大積が動的に更新され、最終的な解が最終的に取得されます。
このような質問の場合、プロセスの最大値と最小値を記録するために、最大値と最小値の2つの変数を定義できます。curは、計算プロセスで計算される現在のデータを表します。各計算プロセスで、maxはMax。(cur、cur * max、cur * min)の最大値を取り、minはMin。(cur、cur * max、cur * min)の最小値を取ります。
特定の手順
1)cur、max、minデータを初期化します。デフォルトは最初の数値です。
2)配列要素をループします。
3)ループmax、minのたびに、現在の要素curが乗算されます。一時変数で保存します。
4)新しい最大値と最小値を計算し、それらを再割り当てします。
5)計算プロセスにおける新しい最大値ans = Max(max、ans)。
6)トラバースした後、ansを印刷します。
3.コードの実装
import java.util.Scanner;
public class Main {
static long[] nums;// 用来存放数据
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt();
/**
* long cur 当前数据 long max 最大数 long min 最小数 long ans 最终结果
*/
long cur, max, min, ans = 0;
// 录入数据
for (int i = 0; i < m; i++)
nums[i] = scanner.nextLong();
// 初始化数据,默认都为第一个数
cur = nums[0];
max = nums[0];
min = nums[0];
for (int i = 1; i < m; i++) {
cur = nums[i];// 当前处理的数
long tempmax = max * cur;// 当前数cur乘以最大数max,定义一个临时变量tempmax储存
long tempmin = min * cur;// 当前数cur乘以最小数min,定义一个临时变量tempmin储存
// 新的max在上面三个数中产生
/* 因为max在下一步求min时还要用到,因此这里定义一个临时变量储存newmax */
long newmax = Math.max(cur, Math.max(tempmax, tempmin));
min = Math.min(cur, Math.min(tempmax, tempmin));
max = newmax;// max使用完后,将新的newmax赋值给max
ans = Math.max(ans, max);// 数据处理过程中的答案在ans和max中产生
}
System.out.println(ans);
}
}
4.DPの概要
知らせ
動的計画法(動的計画法)アルゴリズムの核となるアイデアは、大きな問題を小さな問題に分割して解決し、最適な解決策を段階的に取得することです。
動的計画法アルゴリズムは、分割と征服のアルゴリズムに似ていますが、その基本的な考え方は、解決する問題をいくつかのサブ問題に分解し、最初にサブ問題を解決し、次にこれらのサブ問題の解決策から元の問題の解決策を取得することです。
分割統治法とは異なり、分解によって得られるサブ問題は、動的計画法による解決に適した問題について、互いに独立していないことがよくあります。(つまり、次のサブステージの解は前のサブステージの解に基づいており、さらに解が実行されます。)
フォームに入力することで動的計画法を徐々に進めて、最適な解を得ることができます。