POJ 1651乗算パズルセクションDP
一連の数値が与えられた場合、コストを最小限に抑えるために、途中にあるすべての数値を削除するようにしてください。数値の1つを取得するコストは、この数値とその左右の積です。
解決策:
定期的な間隔DP、列挙間隔の長さ、列挙の開始点、および列挙分割点(ここでの分割点とは、範囲内で最後に取り除かれる数を示す分割点です!この質問で検討する唯一の点である可能性があります)の書き込みを考慮してください。
dp [i] [j]がiからjまでのすべての数値の最小コストを表し、a [i]が位置iの数値を表すとします。
dp [i] [j] = min(dp [i] [k-1] + dp [k + 1] [j] + a [i-1] * a [k] * a [j + 1])( k = i ... j-1)
最小値が考慮されるため、配列は次のように前処理する必要があります。
dp [i] [i-1] = 0;
dp [i] [i] = a [i] * a [i + 1] * a [i-1]
その他のdp [i] [j] = INF;
#include <iostream> #include <cstring> #include <stdio.h> #include <algorithm> using namespace std; const int N = 105; int dp [N] [N]; int a [N]; int main() { int n; scanf( "%d"、&n); for(int i = 0; i <n; i ++){ scanf( "%d"、&a [i]); } memset(dp、0x3f、sizeof(dp)); for(int i = 1; i <n; i ++) dp [i] [i-1] = 0; for(int i = 1; i <n-1; i ++){ dp [i] [i] = a [i] * a [i-1] * a [i + 1]; } for(int len = 1; len <= n-2; len ++){ for(int i = 1; i + len-1 <n-1; int end = i + len-1; for(int k = i; k <= end; k ++){ dp [i] [end] = min(dp [i] [end]、dp [i] [k-1] + dp [k + 1] [ end] + a [k] * a [i-1] * a [end + 1]); } } } printf( "%d \ n"、dp [1] [n-2]); 0を返します。 }
一連の数値が与えられた場合、コストを最小限に抑えるために、途中にあるすべての数値を削除するようにしてください。数値の1つを取得するコストは、この数値とその左右の積です。
解決策:
定期的な間隔DP、列挙間隔の長さ、列挙の開始点、および列挙分割点(ここでの分割点とは、範囲内で最後に取り除かれる数を示す分割点です!この質問で検討する唯一の点である可能性があります)の書き込みを考慮してください。
dp [i] [j]がiからjまでのすべての数値の最小コストを表し、a [i]が位置iの数値を表すとします。
dp [i] [j] = min(dp [i] [k-1] + dp [k + 1] [j] + a [i-1] * a [k] * a [j + 1])( k = i ... j-1)
最小値が考慮されるため、配列は次のように前処理する必要があります。
dp [i] [i-1] = 0;
dp [i] [i] = a [i] * a [i + 1] * a [i-1]
その他のdp [i] [j] = INF;
#include <iostream> #include <cstring> #include <stdio.h> #include <algorithm> using namespace std; const int N = 105; int dp [N] [N]; int a [N]; int main() { int n; scanf( "%d"、&n); for(int i = 0; i <n; i ++){ scanf( "%d"、&a [i]); } memset(dp、0x3f、sizeof(dp)); for(int i = 1; i <n; i ++) dp [i] [i-1] = 0; for(int i = 1; i <n-1; i ++){ dp [i] [i] = a [i] * a [i-1] * a [i + 1]; } for(int len = 1; len <= n-2; len ++){ for(int i = 1; i + len-1 <n-1; int end = i + len-1; for(int k = i; k <= end; k ++){ dp [i] [end] = min(dp [i] [end]、dp [i] [k-1] + dp [k + 1] [ end] + a [k] * a [i-1] * a [end + 1]); } } } printf( "%d \ n"、dp [1] [n-2]); 0を返します。 }