# TD 1 -- Algorithme
###### tags `TD` `M1 S1` `Algorithme`
[Sommaire](/ueYXUIJIQ6C6hcYzKYeojA)
> [time= 16 sept 2020]
[TOC]
## ++Exercice 1++: le problème des fous sur un échiquier n × n
### Enoncer
On veut placer un nombre maximal de fous sur un échiquier de taille n × n sans que les fous se menacent mutuellement. On rappelle qu’un fou menance toutes les cases qui se trouvent sur les deux diagonales passant par sa case.
1. Sur un échiquier de taille 2 × 2 (3 × 3, 4 × 4) combien de fous peut-on placer sans qu’ils se menacent ?
2. Donnez un algorithme pour résoudre le problème.
3. Modifiez cet algorithme pour obtenir également le placement des fous.
4. Évaluer la complexité de l’algorithme.
### Réponse
#### 1)
n = 2 -> 2 fous
```csvpreview
F,.
F,.
```
n = 3 -> 4 fous
```csvpreview
F,.,.
F,.,F
F,.,.
```
n = 4 -> 6 fous
```csvpreview {delimiter=","}
F,.,.,.
F,.,.,F
F,.,.,F
F,.,.,.
```
#### 2)
```python=
def est_menace(l, i, j):
"""
test si le placement d'un fous en i, j
menace le jeux
l: list
liste contenant la liste
des positions des trous déja places
i: int
ligne de l'élément à tester
j: int
colonne de l'élément à tester
"""
if not l:
return False
i1, j1 = l[0]
if abs(i - i1) == abs(j - j1):
return True
return est_menace(l[1:], i, j)
```
```python=+
def fous_nombre(n):
"""
resous le probleme des fous
sur une grille de n
n: int
taille de la grille
"""
def fous(l):
"""
resoud le probleme des fous
en donnant le nomre de fous possible
"""
r_max = len(l)
for i in range(n):
for j in range(n):
if not est_menace(l, i, j):
res = fous(l + [(i, j)])
if res > r_max:
r_max = res
return r_max
return fous([])
```
#### 3)
```python=+
def fous_placement(n):
"""
resous le probleme des fous
sur une grille de n
n: int
taille de la grille
"""
def fous(l):
"""
resoud le probleme des fous
en donnant le nomre de fous possible
"""
r_max = len(l)
l_max = l
for i in range(n):
for j in range(n):
if not est_menace(l, i, j):
res, res_l = fous(l + [(i, j)])
if res > r_max:
r_max = res
l_max = res_l
return r_max, l_max
return fous([])
```
#### 4)
La compléxité est en (n^2^)^n^
## ++Exercice 2++: plus longue sous-suite croissante
### Enoncé
Plus longue sous-suite croissante
On s’intéresse au problème suivant : étant donné une liste L d’entiers, déterminer une suite strictement croissante d’indices $i_1 < \dotsc < i_l$, de longueur $l$ maximale, telle que $L[i_1] \leq L[i_2] \leq \dotsc \leq L[i_l]$.
1. Proposer un algorithme de type « backtracking » permettant de calculer la longueur maximale d’une sous-suite croissante.
2. Donner une relation de récurrence structurelle qui correspond à cet algorithme.
3. Modifier cet algorithme pour obtenir l’une des plus longues sous-suites croissantes, puis
pour compter ces plus longues sous-suites croissantes.
4. Évaluer la complexité de ces algorithmes.
### Réponse
exemple
| | | - | - | - | | - | - | - | | | |
| - | - | - | - | - | - | - | - | - | - | - | - |
| $-\infty$ | 2 | 1 | 3 | 4 | 2 | 5 | 6 | 7 | 3 | 4 | 5 |
#### 1)
```python=
def plssc(pre, l):
"""
plus longue sous suite croissante
pre : int
on donne -infi par défaut
est le rédécesseur
l : list
list des n élément à inspecté
"""
if not l:
return 0
elif pre <= l[0]:
skip = plssc(pre, l[1:])
take = plssc(l[0], l[1:])
return max(skip, take + 1)
return plssc(pre, l[1:])
```
ou
```python=
def plssc_longeur(l):
l = [min(l) - 1] + l
def plssc(i, j):
"""
plus longue sous suite croissante
pre : int
on donne -infi par défaut
est le rédécesseur
l : list
list des n élément à inspecté
"""
if j >= len(l):
return 0
elif l[i] <= l[j]:
skip = plssc(l[i], j + 1)
take = plssc(l[j], j + 1)
return max(skip, take + 1)
return plssc(i, j + 1)
return plssc(0, 1)
```
#### 2)
$$
plssc(pre, A)=
\begin{cases}
0 & \text{si }n\text{ |L| = 0} \\
\begin{align}
\max(& plssc(pre, A[1:]),\\
& plssc(A[0], A[1:]) + 1)
\end{align}
& \text{si } \: pre \leq A[0]\\
plssc(pre, A[1:])
\end{cases}
$$
#### 4)
- si la liste est croissante (*l14 à l17*) on a une compléxité en **2^n^**
- si elle est décroissante (*l19*) on a une compléxité en **n**