problème de la multiplication de la chaîne Matrix: chaîne de matrice donnée de n <A1, A2, A3, ... , An>, la taille de la matrice Ai . système de crochets COMPLETE, de sorte que calculate A1A2 produit ... Un nombre minimum requis de multiplications scalaire.
annuaire
Tout d'abord, l'analyse de l'algorithme
1, les dispositifs supports les caractéristiques structurelles optimales
2, un programme récursif pour résoudre
Optimisation de la Méthode d'écriture - complexité temporelle est
La méthode optimisée - la complexité temporelle tombe
2, assemblage solution optimale
1, problème de la multiplication des chaînes de matrice
Complet Code 1 AC :( complexité temporelle unoptimized )
Code complet AC 2 :( optimisation de la complexité du temps )
Complet Code 1 AC :( complexité temporelle unoptimized )
Code complet AC 2 :( optimisation de la complexité du temps )
Lorsque seuls deux matrices A et B sont compatibles, à savoir, le nombre de colonnes égal au nombre de lignes A, B, peut multiplié. Si A est un p × q matrice, B est q × r matrice, le produit C est le p × matrice de r. C ont été calculées en PQR multiplications. Nous employons un certain nombre de fois multiplication pour représenter le coût de l' informatique .
Pour plus d' matrice se multiplient sans cesse le problème, nous appelons les enjeux de la chaîne Matrix. La multiplication de matrices est associative, de sorte que toute méthode de parenthèses ne modifie pas le résultat d'une pluralité de multiplication de matrice. Cependant, différents entre parenthèses Schemes (modification de l' ordre de calcul) auront une incidence sur le calcul des coûts de la chaîne de multiplication de la matrice:
Tout d'abord, l'analyse de l'algorithme
1, les dispositifs supports les caractéristiques structurelles optimales
La première étape de la méthode de programmation dynamique est de trouver la sous-structure optimale, vous pouvez utiliser cette infrastructure, la solution optimale du problème initial de destructor optimal créer des problèmes.
(Pour plus de commodité, nous noterons la matrice de résultat de la multiplication)
- De toute Partielle apparence: une matrice pour chaque chaîne , si leurs supports, nous devrions être en deux matrices et divisée entre ouverte, nous allons discuter et supports de.
- A partir de là à l'ensemble locale Voir: le calcul coût = calculer le calcul coût + coût + calculé le coût.
Par conséquent, afin de construire une chaîne de matrice solution problème de multiplication optimale, nous pouvons décomposer le problème en deux sous-problèmes: et l' optimisation parenthèses problème. Après la question de la solution sous-optimale est obtenue, alors la solution sous-optimale du problème de la combinaison .
2, un programme récursif pour résoudre
- La taille de la matrice correspondant à la stockée réseau à une dimension p [0..n] , la matrice de taille est .
- Calcul du coût de la mémoire correspondante dans la matrice à deux dimensions ans [1..n, 1..n] , nous avons utilisé ans [i, j] désigne une matrice coût de calcul minimal, le coût de calcul du minimum du problème d' origine en finale ANS [ 1, n] à l'intérieur.
- point de division optimale correspondant au stocké à deux dimensions fracture de la matrice [1..n, 1..n] , nous utilisons le clivage [i, j] enregistre les ans de coût optimal [i, j] correspondant au point de division optimal d. (Ce tableau est utile lors de l' impression de la structure optimale)
Selon les caractéristiques structurelles décrites ci-dessus du schéma optimal des supports, on peut citer l'équation de transition d'état:
- Lorsque i = j lorsque:
- Quand i <j lorsque:
ps: lors de la définition du réseau SNA tous initialisés à zéro.
En second lieu, l'algorithme
1, calculer le coût optimal
L' analyse est connue de l'algorithme, les besoins en question à ascendantes méthodes: problème d'optimisation pour gérer la chaîne de sous-matrices, puis pris ensemble.
Alors, quand nous avons réalisé: Il devrait être la longueur de la matrice de la chaîne 2 a commencé à discuter, puis discuter de la longueur de la matrice de la chaîne 3 ... n la discussion finale de la longueur de la matrice de la chaîne, qui est d'obtenir une réponse sur cette base. Longuement a été déterminée en discussion, ne fuira pas le cas, ou aurait une incidence sur la valeur optimale.
Optimisation de la Méthode d'écriture - complexité temporelle est
Ensuite , notre structure en boucle devrait ressembler à ceci:
- La première boucle de couche: longueur L = 2..n
- La deuxième boucle de couche: l'examen de chaque longueur de la matrice de la chaîne de l : i = 1..n - l 1, j = i + l + 1
- La troisième boucle de couche: la détermination d'un point de division optimal k = i..j-1
/* 计算n元矩阵链p的最优代价
* 动态规划的每一步结果储存在 ans与 divide中 */
void MatrixChainOrder(int p[], int n) {
/* 矩阵链长度为2到n */
for (int l = 2; l <= n; l++) {
/* 讨论长度为l的矩阵链A[i..j] */
for (int i = 1; i <= n - l + 1; i++) {
int j = i + l - 1;
ans[i][j] = INT_MAX;
/* 依次讨论每一个分割点d:将矩阵链A[i..j]分成A[i..d]和 A[d+1..j] */
for (int temp, d = i; d < j; d++) {
temp = ans[i][d] + ans[d + 1][j] + p[i - 1] * p[d] * p[j];
/* 记录下矩阵链A[i..j]最小的情况 */
if (temp < ans[i][j]) {
ans[i][j] = temp;
divide[i][j] = d;
}
}
}
}
}
La méthode optimisée - la complexité temporelle tombe
Trois méthodes de base au- dessus du cycle est inévitable, mais peut réduire considérablement le nombre de cycles pour traverser une troisième couche, de sorte que la complexité de temps est réduit . Selon la chaîne matrice modèle les caractéristiques du problème, sa dynamique Solver peut utiliser l' optimisation des inégalités quadrangulaire . ( Les liens sont détaillés principe d'optimisation, la complexité temporelle du processus de certification)
Ainsi , les satisfait au point de décision optimal du relation: si nous troisième boucle de couche peut être optimisée de la manière suivante: Dans un intervalle particulier [ Divide [I] [J -1], Diviser [+ +1 i] [j] ] à l'intérieur de la traverse, laquelle plage de déplacement beaucoup moins que n.
ps: attention aux cas de limites, il est nécessaire de diviser le prêt initial.
/* 计算n元矩阵链p的最优代价
* 动态规划的每一步结果储存在 ans与 divide中 */
void MatrixChainOrder(int p[], int n) {
/* 初始化divide数组 */
for (int i = 1; i <= n; i++)
divide[i][i] = i;
/* 矩阵链长度为2到n */
for (int l = 2; l <= n; l++) {
/* 讨论长度为l的矩阵链A[i..j] */
for (int i = 1; i <= n - l + 1; i++) {
int j = i + l - 1;
ans[i][j] = INT_MAX;
/* 在特定区间内:依次讨论每一个分割点d,将矩阵链A[i..j]分成A[i..d]和 A[d+1..j] */
for (int temp, d = divide[i][j - 1]; d <= divide[i + 1][j]; d++) {
temp = ans[i][d] + ans[d + 1][j] + p[i - 1] * p[d] * p[j];
/* 记录下矩阵链A[i..j]最小的情况 */
if (temp < ans[i][j]) {
ans[i][j] = temp;
divide[i][j] = d;
}
}
}
}
}
2, assemblage solution optimale
Dans le tableau on divise en deux dimensions [i, j] a été enregistrée dans le point de coupe optimal, étant donné que la matrice de la chaîne de division optimale peut être décomposé en chaîne de division de sous-optimale, de sorte que l' on peut récursivement imprimé.
/* 根据divide数组,输出A[i..j]的最优情况 */
void PrintDivide(int i, int j) {
if (i == j)
printf("A%d", i);
else {
int d = divide[i][j]; //找到分界点
printf("(");
PrintDivide(i, d);
PrintDivide(d + 1, j);
printf(")");
}
}
Exemples Troisièmement,
1, problème de la multiplication des chaînes de matrice
réalisation | dix | le temps | 2020 10 Mars Mardi, 07h55 |
rabais | 0,8 | Temps Discount | 2020 mardi, 7 Avril 23h55 |
Autoriser fin | aucun | temps de fermeture | 2020 mardi, 7 Avril 23h55 |
entrée:
Un total de deux lignes
La première rangée N (1 <= N <= 100), représentatif du nombre de matrices.
La seconde ligne comporte le nombre de N + 1, respectivement, A1, A2 ...... An + 1 (1 <= Ak <= 2000), Ak et Ak + 1 représente le k une matrice Ak X Ak + 1 en forme.
sortie:
Un total de deux lignes
La première ligne M, est le coût optimal. Note: le cas de test pour vous assurer que moins de 2 ^ M valeur 31
ordre optimal de la deuxième loi. Les, mais aussi les parenthèses les plus extérieures (A1 (A2A3) (A4)).
Note: Le test doit veiller à ce que la sortie de la semelle, donc il n'y a pas de situation de l'AAA.
entrée test | Résultats attendus | délai | mémoire limite | processus supplémentaire | |
---|---|---|---|---|---|
Test Case 1 |
|
|
1 seconde | 64M | 0
|
La méthode en détail spécifique a été expliqué ci-dessus, il ~
Principale Note: Lorsque le nombre de la matrice de la chaîne de la matrice pour produire un parenthésée, ou sera un wa.
Complete AC Code 1: (unoptimized complexité temporelle)
//
// Created by LittleCat on 2020/3/10.
//
#include <cstdio>
#include <climits>
using namespace std;
#define MAX 2010
int ans[MAX][MAX] = {0}; // 保存矩阵链 A[i..j]的最小代价
int divide[MAX][MAX] = {0}; // 记录最小代价ans[i,j]对应的分割点
/* 计算n元矩阵链p的最优代价
* 动态规划的每一步结果储存在 ans与 divide中 */
void MatrixChainOrder(int p[], int n) {
/* 矩阵链长度为2到n */
for (int l = 2; l <= n; l++) {
/* 讨论长度为l的矩阵链A[i..j] */
for (int i = 1; i <= n - l + 1; i++) {
int j = i + l - 1;
ans[i][j] = INT_MAX;
/* 依次讨论每一个分割点d:将矩阵链A[i..j]分成A[i..d]和 A[d+1..j] */
for (int temp, d = i; d < j; d++) {
temp = ans[i][d] + ans[d + 1][j] + p[i - 1] * p[d] * p[j];
/* 记录下矩阵链A[i..j]最小的情况 */
if (temp < ans[i][j]) {
ans[i][j] = temp;
divide[i][j] = d;
}
}
}
}
}
/* 根据divide数组,输出A[i..j]的最优情况 */
void PrintDivide(int i, int j) {
if (i == j)
printf("A%d", i);
else {
int d = divide[i][j]; //找到分界点
printf("(");
PrintDivide(i, d);
PrintDivide(d + 1, j);
printf(")");
}
}
int main() {
int n;
scanf("%d", &n);
int p[MAX];
for (int temp, i = 0; i <= n; i++)
scanf("%d", &p[i]);
MatrixChainOrder(p, n);
printf("%d\n", ans[1][n]);
if (n == 1)
printf("(A1)");
else
PrintDivide(1, n);
printf("\n");
}
Complete AC Code 2: (optimisation de la complexité du temps)
//
// Created by LittleCat on 2020/3/10.
//
#include <cstdio>
#include <climits>
using namespace std;
#define MAX 2010
int ans[MAX][MAX] = {0}; // 保存矩阵链 A[i..j]的最小代价
int divide[MAX][MAX] = {0}; // 记录最小代价ans[i,j]对应的分割点
/* 计算n元矩阵链p的最优代价
* 动态规划的每一步结果储存在 ans与 divide中 */
void MatrixChainOrder(int p[], int n) {
/* 初始化divide数组 */
for (int i = 1; i <= n; i++)
divide[i][i] = i;
/* 矩阵链长度为2到n */
for (int l = 2; l <= n; l++) {
/* 讨论长度为l的矩阵链A[i..j] */
for (int i = 1; i <= n - l + 1; i++) {
int j = i + l - 1;
ans[i][j] = INT_MAX;
/* 在特定区间内:依次讨论每一个分割点d,将矩阵链A[i..j]分成A[i..d]和 A[d+1..j] */
for (int temp, d = divide[i][j - 1]; d <= divide[i + 1][j]; d++) {
temp = ans[i][d] + ans[d + 1][j] + p[i - 1] * p[d] * p[j];
/* 记录下矩阵链A[i..j]最小的情况 */
if (temp < ans[i][j]) {
ans[i][j] = temp;
divide[i][j] = d;
}
}
}
}
}
/* 根据divide数组,输出A[i..j]的最优情况 */
void PrintDivide(int i, int j) {
if (i == j)
printf("A%d", i);
else {
int d = divide[i][j]; //找到分界点
printf("(");
PrintDivide(i, d);
PrintDivide(d + 1, j);
printf(")");
}
}
int main() {
int n;
scanf("%d", &n);
int p[MAX];
for (int temp, i = 0; i <= n; i++)
scanf("%d", &p[i]);
MatrixChainOrder(p, n);
printf("%d\n", ans[1][n]);
if (n == 1)
printf("(A1)");
else
PrintDivide(1, n);
printf("\n");
}
2. pierres consolidées
Le problème des pierres combinées: linéaire arrangé pierres entassées N, Pierre est maintenant fusionné dans une pile. Il se lit comme suit: vous ne pouvez fusionner des tas de gravier adjacentes, des tas de pierres prend la consolidation temporelle du nombre de piles et de pierres. La fusion cherchent de temps en pierres N entassées coût minimum de pile. (N pierres dans la pile, le nombre de pierres sont stockées dans un tableau en)
Ce qui suit est un n = 4, p = {4, 2, 3, 4} exemple, le temps minimum qu'il faut pour 26.
Cette question est essentiellement un problème de multiplication de la chaîne matricielle - choisir deux noeuds adjacents chaque fusion de la chaîne, jusqu'à ce que toute la fusion est terminée jusqu'à présent. Le procédé combiné de la pierre est placée entre crochets dans le processus de la chaîne de la matrice.
Ce problème est également un problème avec une structure sous-optimale:
Afin de construire un tas de pierres des solutions combinées, nous pouvons décomposer le problème en deux sous-problèmes: et la fusion des pierres. Après la question de la solution sous-optimale est obtenue, alors la solution sous-optimale du problème de la combinaison .
Vous cherchez un programme dynamique pour la résolution récursive:
Le coût combiné de stockage correspondants dans les ans de matrice à deux dimensions [0..n-1, 0..n- 1] , nous avons utilisé ans [i, j] représente une pierre de cheminée combinés coût d' un temps de comptage minimum, de sorte que le minimum du problème d' origine l'examen final dans les ans de calcul [1, n] à l'intérieur.
équation de transition d'état:
- Lorsque i = j lorsque:
- Quand i <j lorsque:
ps: lors de la définition du réseau SNA tous initialisés à zéro.
Complete AC Code 1: (unoptimized complexité temporelle)
Le noyau est un cycle de trois parties
- La première boucle de couche: longueur L = 2..n
- La deuxième boucle de couche: l'examen de chaque longueur de pierres de pile l : i = 1..n - l 1, j = i + l + 1
- La troisième boucle de couche: la détermination d'un point de division optimal k = i..j-1
Être vu, la complexité temporelle de ce code
#define N 100
#include <cstdio>
#include <climits>
/* 合并石子问题:线性排列着N堆石子,现在要将石子合并成一堆。
* 规定如下:每次只能将相邻的两堆石子合并,合并两堆石子所花费的时间为两堆石子的数量和。
* 求将N堆石子合并成一堆最小花费的时间。(石子分为n堆,石子的数量存储在数组p[0..n-1]中)*/
int ans[N][N] = {0};
int MergeStone(int p[], int n) {
/* 石子堆的个数:从1到n */
for (int l = 2; l <= n; l++) {
/* 讨论l个石子的石子堆 p[i..j] */
for (int i = 0; i < n - l + 1; i++) {
int j = i + l - 1, sum = 0;
/* 计算p[i..j]的石子总和 */
for (int t = i; t <= j; t++)
sum += p[t];
ans[i][j] = INT_MAX;
/* 依次讨论每一个分割点d:将石子堆p[i..j]分成p[i..k]和 A[k+1..j] */
for (int temp, k = i; k < j; k++) {
temp = ans[i][k] + ans[k + 1][j] + sum;
if (temp < ans[i][j])
ans[i][j] = temp;
}
}
}
return ans[0][n - 1];
}
Complete AC Code 2: (optimisation de la complexité du temps)
#define N 100
#include <cstdio>
#include <climits>
/* 合并石子问题:线性排列着N堆石子,现在要将石子合并成一堆。
* 规定如下:每次只能将相邻的两堆石子合并,合并两堆石子所花费的时间为两堆石子的数量和。
* 求将N堆石子合并成一堆最小花费的时间。(石子分为n堆,石子的数量存储在数组p[0..n-1]中)*/
//优化版本!!!!
int ans[N][N] = {0};
int divide[N][N];
int MergeStone(int p[], int n) {
/* divide数组初始化*/
for (int i = 0; i < n; i++)
divide[i][i] = i;
/* 石子堆的个数:从1到n */
for (int l = 2; l <= n; l++) {
/* 讨论l个石子的石子堆 p[i..j] */
for (int i = 0; i < n - l + 1; i++) {
int j = i + l - 1, sum = 0;
/* 计算p[i..j]的石子总和 */
for (int t = i; t <= j; t++)
sum += p[t];
ans[i][j] = INT_MAX;
/* 依次讨论特定区间内分割点d:将石子堆p[i..j]分成p[i..k]和 A[k+1..j] */
for (int temp, k = divide[i][j - 1]; k <= divide[i + 1][j]; k++) {
temp = ans[i][k] + ans[k + 1][j] + sum;
if (temp < ans[i][j]) {
ans[i][j] = temp;
divide[i][j] = k; //更新p[i..j]的石子堆的最优分割位置
}
}
}
}
return ans[0][n - 1];
}
Toute question, veuillez examiner l'échange, si vous le souhaitez cet article peu utile de louange, hee hee ~
fin
Aucune attention de bienvenue personnelle au public « ailes de poulet Programmation » , voici un code d' une agriculture sérieuse et bien élevé.
---- faire le blog le plus sage er, faire le plus programmeur solide ----
Vise à écrire soigneusement chaque article, généralement regroupées en notes poussera les mises à jour -