動的計画の問題-------ランチャオカップの実際の問題-------ブルーブリッジカップの準備

デジタルトライアングル

画像の説明

上の図はデジタル三角形を示しています。三角形の上から下まで、さまざまなパスがあります。パスごとに、パス上の数値を合計して合計を取得します。タスクは、最大の合計を見つけることです。

パスの各ステップは、1つの番号から、それに最も近い次のレベルの左側または右側の番号にのみ移動できます。また、左に下がる回数と右に下がる回数の差は1を超えることはできません

説明を入力してください

入力の最初の行は、整数N(1≤含まN三角形の数を表す≤100)を、。

以下N Nの行は、デジタル三角形を与えます。デジタル三角形の数字はすべて0〜100の整数です。

出力の説明

答えを示す整数を出力します。

サンプルの入力と出力

入る

5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

出力

27

動作制限

  • 最大実行時間:1秒
  • 最大動作メモリ:256M

最初に行うことを行うために動的計画法を使用することを思い出さなかった場合は、デジタル三角形を格納するために2次元配列を使用することを確実に考えることができます。わかりやすくするために、より直感的に描画します。木によって)

ここに画像の説明を挿入

アイデア

質問の意味に応じて、上記から最大値を計算します。最初は、補助配列を使用して値を格納し、合計して最大値を確認したかったのですが、それもそうです。面倒です。数値を直接変更できます。三角形を使用してパス値を取得します。

問題は、分岐アルゴリズムを使用できるかどうかです。私たちが取るすべてのステップは必ずしも同じではない、つまり、私たちが取るすべてのステップは独立していることがわかりました。あなたが取るこのステップが最大の価値であるかどうか誰が知っていますか?

つまり、動的計画法の方法を検討する必要があります。次のステップは、前のステップの結果に関連しています。前のステップに基づいて構築され、動的計画法に適合します。

隣接するデジタルパスの次の行のみをたどることができます。各ステップは同じです。これは同じポイントです。次のステップの結果は、前のステップの結果に基づいて確立されます。すべて動的計画法に準拠しているため、動的計画法を使用してください

コード

public class 数字三角形 {
    
    
	public static void main(String[] args) {
    
    
		 Scanner scan = new Scanner(System.in);
	     //在此输入您的代码...
		 //1.二维数组来存储我们的三角形
		 //1.1我们的行数
		 int N = scan.nextInt();
		 int[][] arr = new int[N+1][N+1];
		 //1.2生成数字三角形
		 for (int i = 1; i <= N; i++) {
    
    
			for (int j = 1; j <= i; j++) {
    
    
				arr[i][j] = scan.nextInt();
			}
		 }
		 //2.计算我们的最大值
		 for (int i = 1; i <= N; i++) {
    
    
			for (int j = 1; j <= i; j++) {
    
    
				arr[i][j] = arr[i][j] + Math.max(arr[i-1][j], arr[i-1][j-1]);
			}
		}
		 //
		 if(N%2 != 0){
    
    
			 System.out.println(arr[N][N/2+1]);
		 }else{
    
    
	         System.out.println(Math.max(arr[N][N/2+1],arr[N][N/2]));
		 }
	     scan.close();
	}
}

最初は見たことがなかったので、解決策がわからなかったので、段階的にデバッグして彼の考えを理解する必要がありました。絵を描くだけで簡単に理解できます。

最初のステップ

arr [1] 1 = arr [1] 1 + max [0] [1は無意味であり、最初のラウンドで結果はありません

第二段階

i = 2 j = 1

arr[2][1] = arr[2][1] + Math.max(arr[1][1], arr[1][0]); ==>  10

i = 2 j = 2

arr[2][2] = arr[2][2] + Math.max(arr[1][2], arr[1][1]);
		  =  8        +       0         7   = 15

ここに画像の説明を挿入

3番目のステップ

i = 3 j = 1

arr[3][1] = arr[3][1] + Math.max(arr[2][1], arr[2][0]); ==>
    			8	+		(10,0)     =   18

i = 3 j = 2

arr[3][2] = arr[3][2] + Math.max(arr[2][2], arr[2][1]); ==>  
     			1    +   (15,10)      =  16

i = 3 j = 3

arr[3][3] = arr[3][3] + Math.max(arr[2][3], arr[2][2]); ==> 
    			0	+		(0,15)			 =    15

4番目のステップ

同じ手順が

ここに画像の説明を挿入

ついに

ここに画像の説明を挿入

別の質問があります。30が最大であることがわかっているのに、なぜ27の答えなのですか。

主な理由は、私たちの問題では、左に下がる回数と右に下がる回数の差が1を超えてはならないということです。これをどのように理解しますか?

30がどのように来たのかを見てください。7387 5、そのうち7 3 8 5が右に3回、7が左に1回だけ下がったので、質問の意味を満たしていません。差が1以下の場合、中央の値である必要があるため、27になります。

おすすめ

転載: blog.csdn.net/qq_22155255/article/details/114481570
おすすめ