Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
j'espère avoir été clair. si question n'hésitez pas..
Merci pour vos pistes
NB : naturellement le commencerais par le tableau le plus haut... mais est
ce bien cela ..
Faut il tester toutes les possibilités ?
Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
j'espère avoir été clair. si question n'hésitez pas..
Merci pour vos pistes
NB : naturellement le commencerais par le tableau le plus haut... mais est
ce bien cela ..
Faut il tester toutes les possibilités ?
Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
j'espère avoir été clair. si question n'hésitez pas..
Merci pour vos pistes
NB : naturellement le commencerais par le tableau le plus haut... mais est
ce bien cela ..
Faut il tester toutes les possibilités ?
Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
"Driss HANIB" a écrit dans le message de news:Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer
des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
http://www.enseignement.polytechnique.fr/profs/informatique/Jean-Jacques.Levy/poly/main8/node8.html
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
Esp As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
max de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
OErx74n9GHA.3384@TK2MSFTNGP05.phx.gbl...
Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer
des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
http://www.enseignement.polytechnique.fr/profs/informatique/Jean-Jacques.Levy/poly/main8/node8.html
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
Esp As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
max de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" a écrit dans le message de news:Bonjour à tous
je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
différentes dans une page.
En détail
sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
et
de pied de page entre lesquelles je peux insérer ce que je veux :
ceci définit donc une hauteur disponible dans laquelle je peux insérer
des
cadres
mon problème est le suivant
pour une situation donnée, j'obtiens un nombre N de tableaux à créer dont
la
hauteur est variable et dépend de la situation : chaque tableau a une
hauteur propre définie par le nombre de lignes de ce tableau, toutes les
lignes étant de hauteur constante.
Exemple :
Tableau 1 : 6 lignes
Tableau 2 : 5 lignes
tableau 3 : 10 lignes
tableau 4 : 5 lignes
tableau 5 : 7 lignes
ce que je cherche est : si la somme des hauteurs des tableaux est
supérieure
à la hauteur disponible (définie plus haut), comment trouver l'ordre mais
surtout les indices des tableaux à imprimer pour que le maximum d'espace
soit utilisé ?
les autres tableaux seont mis (de la même) façon sur la page suivante.
Il est bien entendu que l'espace entre les tableaux est une constante ;
considérer donc que je peux définir les hauteurs occpées par chaque
tableaux.
D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
http://www.enseignement.polytechnique.fr/profs/informatique/Jean-Jacques.Levy/poly/main8/node8.html
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
Esp As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
max de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
> "Patrice Henrio" a écrit dans le message de
news:
cela me rappelle un problème de rouleaux de tapisserie ...
> "Patrice Henrio" <patrice.henrio@laposte.net> a écrit dans le message de
news: uN9qRDt9GHA.1360@TK2MSFTNGP04.phx.gbl...
cela me rappelle un problème de rouleaux de tapisserie ...
> "Patrice Henrio" a écrit dans le message de
news:
cela me rappelle un problème de rouleaux de tapisserie ...
"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
OErx74n9GHA.3384@TK2MSFTNGP05.phx.gbl...
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
OErx74n9GHA.3384@TK2MSFTNGP05.phx.gbl...
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
question avant de tester :
est ce un problème si je passe les hauteur en single, plutot qu'en long ?
Driss
"Jean-marc" a écrit dans le
message
de news:453d0459$0$21492$"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge
> d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
des> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
dont> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes
> les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
mais> surtout les indices des tableaux à imprimer pour que le maximum
> d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
http://www.enseignement.polytechnique.fr/profs/informatique/Jean-Jacques.Levy/poly/main8/node8.htmlA noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
EspAs Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page)
*
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) &
","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur
respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
maxde 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
question avant de tester :
est ce un problème si je passe les hauteur en single, plutot qu'en long ?
Driss
"Jean-marc" <NO_SPAM_jean_marc_n2@yahoo.fr.invalid> a écrit dans le
message
de news:453d0459$0$21492$ba620e4c@news.skynet.be...
"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
OErx74n9GHA.3384@TK2MSFTNGP05.phx.gbl...
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge
> d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
des
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
dont
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes
> les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
mais
> surtout les indices des tableaux à imprimer pour que le maximum
> d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
http://www.enseignement.polytechnique.fr/profs/informatique/Jean-Jacques.Levy/poly/main8/node8.html
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
Esp
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page)
*
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) &
","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur
respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
max
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
FAQ VB: http://faq.vb.free.fr/
question avant de tester :
est ce un problème si je passe les hauteur en single, plutot qu'en long ?
Driss
"Jean-marc" a écrit dans le
message
de news:453d0459$0$21492$"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge
> d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
des> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
dont> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes
> les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
mais> surtout les indices des tableaux à imprimer pour que le maximum
> d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
http://www.enseignement.polytechnique.fr/profs/informatique/Jean-Jacques.Levy/poly/main8/node8.htmlA noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
EspAs Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page)
*
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) &
","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur
respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
maxde 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
OErx74n9GHA.3384@TK2MSFTNGP05.phx.gbl...
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
FAQ VB: http://faq.vb.free.fr/
"Driss HANIB" a écrit dans le message de news:
> Bonjour à tous
>
> je cherche à trouver l'ordre optimal d'insertion de cadres de hauteurs
> différentes dans une page.
>
> En détail
>
> sur feuille (ici de format A4, verticale) j'ai défini des marge d'entête
> et
> de pied de page entre lesquelles je peux insérer ce que je veux :
> ceci définit donc une hauteur disponible dans laquelle je peux insérer
> cadres
>
> mon problème est le suivant
> pour une situation donnée, j'obtiens un nombre N de tableaux à créer
> la
> hauteur est variable et dépend de la situation : chaque tableau a une
> hauteur propre définie par le nombre de lignes de ce tableau, toutes les
> lignes étant de hauteur constante.
>
> Exemple :
>
> Tableau 1 : 6 lignes
> Tableau 2 : 5 lignes
> tableau 3 : 10 lignes
> tableau 4 : 5 lignes
> tableau 5 : 7 lignes
>
> ce que je cherche est : si la somme des hauteurs des tableaux est
> supérieure
> à la hauteur disponible (définie plus haut), comment trouver l'ordre
> surtout les indices des tableaux à imprimer pour que le maximum d'espace
> soit utilisé ?
> les autres tableaux seont mis (de la même) façon sur la page suivante.
> Il est bien entendu que l'espace entre les tableaux est une constante ;
> considérer donc que je peux définir les hauteurs occpées par chaque
> tableaux.
> D'autre part, l'ordre d'écriture des tableaux n'a aucune importance.
>
Et voila...
Bon, voici un algo qui vaut ce qu'il vaut.
Il ne donne pas la solution optimale dans tous les cas,
mais dans tous les cas il donne une solution raisonnable.
Pour une solution "optimale", il faut implémenter l'algorithme
dit du "sac à dos" (Google "algorithme sac a dos"); une bonne
implémentation est disponible ici:
A noter que ce problème est NP complet et que pour trouver une solution
optimale il n'y a pas mieux qu'une exploration systématique récursive
avec un temps de calacuil qui croit exponentiellement.
Revenons à ma solution:
L'idée est de trier les hauteurs (et les indices correspondants),
puis on part du plus grand et on ajoute autant de tableaux que possible
en privilégiant les plus grands d'abord (c'est la différence par rapport
à une implémentation du problème du sac à dos).
Voici la chose:
la fonction comande1 contient un simple appel avec des valeurs de test.
NOTE: j'ai programmé ça vite fait, ce n'est pas forcément
très joli mais ça marche en tout cas :-)
Option Explicit
Private Sub Command1_Click()
Dim HPage As Long
Dim Esp As Long
Dim n As Long
Dim h() As Long
Dim s As String
Dim repart() As String
Dim nb_page As Long
Dim i As Long
HPage = 200
Esp = 10
n = 5
ReDim h(n)
h(1) = 40
h(2) = 18
h(3) = 60
h(4) = 120
h(5) = 90
s = GetRepartTableau(n, h(), HPage, Esp)
If s <> "" Then
repart = Split(s, "#")
For i = LBound(repart()) To UBound(repart())
nb_page = nb_page + 1
Debug.Print "Page " & nb_page & " : " & repart(i)
Next i
Else
' un des tableau à lui tout seul est trop grand
MsgBox "souci, tableau trop grand"
End If
End Sub
Public Function GetRepartTableau(n As Long, h() As Long, HPage As Long,
As Long) As String
Dim t_indice() As Long
Dim t_copy() As Long
Dim i As Long
Dim encore As Boolean
Dim start As Long
Dim cur As Long
Dim hauteur As Long
Dim keep As String
Dim keep2 As String
Dim G_keep As String
Dim G_keep2 As String
Dim nb_used As Long
Dim nb_tab_page As Long
ReDim t_indice(n)
ReDim t_copy(n)
For i = 1 To n
t_indice(i) = i
t_copy(i) = h(i)
Next i
Call ordonne(n, t_indice(), t_copy())
Do
hauteur = 0
encore = True
cur = 1
keep = ""
keep2 = ""
nb_tab_page = 0
Do
If InStr(G_keep, "," & Trim$(Str$(cur)) & ",") = 0 Then
If (hauteur + h(t_indice(cur)) + (nb_tab_page) * Esp) <
HPage Then
hauteur = hauteur + h(t_indice(cur)) + (nb_tab_page) *
Esp
keep = keep & "," & Trim$(Str$(cur)) & ","
keep2 = keep2 & "," & Trim$(Str$(t_indice(cur))) & ","
cur = cur + 1
nb_used = nb_used + 1
nb_tab_page = nb_tab_page + 1
Else
cur = cur + 1
End If
Else
cur = cur + 1
End If
If cur > n Then
Exit Do
End If
Loop
If hauteur = 0 Then
' un des tableaux est trop
'grand pour tenir même tout seul sur une page
MsgBox "probleme"
GetRepartTableau = ""
Exit Function
Else
G_keep = G_keep & keep & "#"
G_keep2 = G_keep2 & keep2 & "#"
End If
If nb_used = n Then
Exit Do
End If
Loop
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, ",,", ",")
G_keep2 = Mid$(G_keep2, 2)
G_keep2 = Mid$(G_keep2, 1, Len(G_keep2) - 1)
G_keep2 = Replace(G_keep2, "#,", "#")
G_keep2 = Replace(G_keep2, ",#", "#")
GetRepartTableau = G_keep2
End Function
Private Sub ordonne(n As Long, indice() As Long, data() As Long)
Dim i As Integer
Dim tmp As Long
Dim encore As Boolean
encore = True
While encore
encore = False
For i = 1 To n - 1
If data(i) < data(i + 1) Then
tmp = data(i)
data(i) = data(i + 1)
data(i + 1) = tmp
tmp = indice(i)
indice(i) = indice(i + 1)
indice(i + 1) = tmp
encore = True
End If
Next i
Wend
End Sub
Sur cet exmple;, le programme trouve:
Page 1 : 4,3
Page 2 : 5,1,2
C'est à dire 2 pages:
sur la premiere le tableau numero 4 et le numero 3, de hauteur respectives
120 et 60, ce qui avec l'intervalle de 10 donne 120+60+10 = 190 (pour un
de 200)
puis sur la page 2, les numeros 5, 1 et 2 c'est à dire:
90+40+18 + 2*10 = 168 (pour le meme max de 200).
J'ai testé sur d'autres cas, ca marche plutot bien :-)
Tout feedback bienvenu :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
>"Driss HANIB" a écrit dans le message de news:
Je viens d'utiliser ton exemple et surtout de le décortiquer (pour
comprendre bien sur)
Et c'est bon sur tous les points. ;o))
j'ai juste remplacé ton keep et G_Keep par un tableau de booléens de même
taille que les tableaux que tu crées et que je mets à jour à chaque
utilisation d'un indice.
Je me suis permis de renommer tes variables pour pouvoir bien comprendre
ton
cheminement.
Je vais maisntenant l'insérer dans mon prog et je te tiens au courant
je me permets de te remettre ma version..
>"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
ecOH3Y49GHA.3312@TK2MSFTNGP02.phx.gbl...
Je viens d'utiliser ton exemple et surtout de le décortiquer (pour
comprendre bien sur)
Et c'est bon sur tous les points. ;o))
j'ai juste remplacé ton keep et G_Keep par un tableau de booléens de même
taille que les tableaux que tu crées et que je mets à jour à chaque
utilisation d'un indice.
Je me suis permis de renommer tes variables pour pouvoir bien comprendre
ton
cheminement.
Je vais maisntenant l'insérer dans mon prog et je te tiens au courant
je me permets de te remettre ma version..
>"Driss HANIB" a écrit dans le message de news:
Je viens d'utiliser ton exemple et surtout de le décortiquer (pour
comprendre bien sur)
Et c'est bon sur tous les points. ;o))
j'ai juste remplacé ton keep et G_Keep par un tableau de booléens de même
taille que les tableaux que tu crées et que je mets à jour à chaque
utilisation d'un indice.
Je me suis permis de renommer tes variables pour pouvoir bien comprendre
ton
cheminement.
Je vais maisntenant l'insérer dans mon prog et je te tiens au courant
je me permets de te remettre ma version..
>"Driss HANIB" a écrit dans le message de news:
>
<réponse inline>Je viens d'utiliser ton exemple et surtout de le décortiquer (pour
comprendre bien sur)
C'est la bonne démarche :-)Et c'est bon sur tous les points. ;o))
Content que ça fonctionne pour toi :-)j'ai juste remplacé ton keep et G_Keep par un tableau de booléens de même
taille que les tableaux que tu crées et que je mets à jour à chaque
utilisation d'un indice.
C'est tout à fait judicieux! J'ai utilisé g_keep par pure fainéantise :o)
La méthode que tu emploies est la meilleure et la plus accadémique.Je me suis permis de renommer tes variables pour pouvoir bien comprendre
ton
cheminement.
Je vais maisntenant l'insérer dans mon prog et je te tiens au courant
super, merci par avance!
je me permets de te remettre ma version..
<snip le (très bon) code>
Juste une minuscule remarque si tu veux bien: on préfère en
général éviter d'utiliser des caractères accentués dans les
noms de variables ( TabUtilisés() ), entre autre par ce que
ce n'est pas très lisible mais surtout par ce qu'il n'y a
pas d'accents sur les claviers qwerty.
En dehors de ce détail, l'adaptation m'à l'air parfaite :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/
>"Driss HANIB" <dhanib@club-internet.fr> a écrit dans le message de news:
>ecOH3Y49GHA.3312@TK2MSFTNGP02.phx.gbl...
<réponse inline>
Je viens d'utiliser ton exemple et surtout de le décortiquer (pour
comprendre bien sur)
C'est la bonne démarche :-)
Et c'est bon sur tous les points. ;o))
Content que ça fonctionne pour toi :-)
j'ai juste remplacé ton keep et G_Keep par un tableau de booléens de même
taille que les tableaux que tu crées et que je mets à jour à chaque
utilisation d'un indice.
C'est tout à fait judicieux! J'ai utilisé g_keep par pure fainéantise :o)
La méthode que tu emploies est la meilleure et la plus accadémique.
Je me suis permis de renommer tes variables pour pouvoir bien comprendre
ton
cheminement.
Je vais maisntenant l'insérer dans mon prog et je te tiens au courant
super, merci par avance!
je me permets de te remettre ma version..
<snip le (très bon) code>
Juste une minuscule remarque si tu veux bien: on préfère en
général éviter d'utiliser des caractères accentués dans les
noms de variables ( TabUtilisés() ), entre autre par ce que
ce n'est pas très lisible mais surtout par ce qu'il n'y a
pas d'accents sur les claviers qwerty.
En dehors de ce détail, l'adaptation m'à l'air parfaite :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ; _no_spam_jean_marc_n2@yahoo.fr
FAQ VB: http://faq.vb.free.fr/
>"Driss HANIB" a écrit dans le message de news:
>
<réponse inline>Je viens d'utiliser ton exemple et surtout de le décortiquer (pour
comprendre bien sur)
C'est la bonne démarche :-)Et c'est bon sur tous les points. ;o))
Content que ça fonctionne pour toi :-)j'ai juste remplacé ton keep et G_Keep par un tableau de booléens de même
taille que les tableaux que tu crées et que je mets à jour à chaque
utilisation d'un indice.
C'est tout à fait judicieux! J'ai utilisé g_keep par pure fainéantise :o)
La méthode que tu emploies est la meilleure et la plus accadémique.Je me suis permis de renommer tes variables pour pouvoir bien comprendre
ton
cheminement.
Je vais maisntenant l'insérer dans mon prog et je te tiens au courant
super, merci par avance!
je me permets de te remettre ma version..
<snip le (très bon) code>
Juste une minuscule remarque si tu veux bien: on préfère en
général éviter d'utiliser des caractères accentués dans les
noms de variables ( TabUtilisés() ), entre autre par ce que
ce n'est pas très lisible mais surtout par ce qu'il n'y a
pas d'accents sur les claviers qwerty.
En dehors de ce détail, l'adaptation m'à l'air parfaite :-)
--
Jean-marc Noury (jean_marc_n2)
MVP Visual Basic
mailto: remove '_no_spam_' ;
FAQ VB: http://faq.vb.free.fr/