#include #include using namespace std; typedef list Li; typedef list::iterator It; typedef list::const_iterator CIt; void llegir(Li &l){ It it=l.end(); int x; cin>>x; while(x!=0){ l.insert(it,x); cin>>x; } } void escriure(int lon, CIt& it){ //Pre: Si la lista apuntada por it no es vacia, it apunta a un elemento de la lista; //la lista contiene al menos lon elementos a partir del elemento apuntado por it. //Si la lista es vacia lon es 0, y it es la posicion end() de la lista. //Post: se escribe por pantalla la sublista que empieza en *it, y contiene los lon //terminos siguientes de la lista apuntada por it. Si la lista es vacia, no se //escribe nada. for(int i=0;i max_long_esc(const Li &v){ //Pre: cert. //Post: el primer componente del resultado es la longitud de la sublista de v mas larga //donde todo elemento es menor o igual que su siguiente. El segundo componente apunta a la //posicion donde se inicia la sublista de longitud maxima de v. En caso de empate apunta //al primer elemento de la escalera de longitud maxima de v mas proxima a v.begin(). Si v //es vacia, el primer componente del resultado es 0, y el segundo es v.end(). pair res; CIt it=v.begin(); CIt it_ant=v.begin(); CIt prim=v.begin(); int tam=0; if(it==v.end()){ res.first=0; res.second=v.begin(); } else{ ++it; res.second=v.begin(); res.first=1; tam=1; } //Inv: //1.v.begin()<=it<=v.end(); //2.Si v no es vacia, it_ant es anterior a it en una posicion. v.begin()<=it_ant v; llegir(v); pair prim_max; prim_max=max_long_esc(v); escriure(prim_max.first, prim_max.second); } Inicializaciones: Después de las inicializaciones, se cumple el invariable. Tenemos que considerar dos casos, v vacía o no. Si v es vacía, it=v.end(), y por tanto se cumple el punto 1 del invariante. A más, res.first=0 y res.second=v.begin(), y por tanto automaticamente se cumplen 5 y 6. Si v no es vacía, it_ant está en la primera posición, y it en la siguiente o v.end() según el tamaño de v. En cualquier caso se cumplen 1 y 2. prim es v.begin(), y por tanto apunta a la primera posición de la lista que empieza y acaba en la posición apuntada por it_ant, cumpliéndose 4. El punto 3 también se cumple porque el tamaño de la lista actual hasta it_ant es 1, i tam se inicializa a 1. Finalmente, se cumplen 5 y 6, porque la subsista actual solo contiene lo apuntado por it_ant, la longitud es 1, y su inicio es la posición v.begin() que en este caso es igual a la posición it_ant. Justificación del bucle: Suponemos que en una iteración cualquiera, al entrar en el bucle se cumple el invariante. Tras ejecutar las instrucciones del bucle, se ha de volver a cumplir el invariante. Los puntos 1 y 2 del invariante se cumplen al salir del bucle, porque al inicio v.begin()<=it<=v.end(), it!=v.end() (condición de entrada en el bucle), v.begin()<=it_ant*it, ejecutamos tam=1 y prim=it. Finalmente movemos una posición it_ant y it. En este caso una escalera finaliza en la posición it_ant, y otra empieza en it. Hasta ese momento tam era el tamaño de la escalera que finaliza en it_ant. Como ahora it_ant se ha movido una posición, tam=1 es correcto, porque solo estamos considerando la escalera que contiene el elemento apuntado por el antiguo it or el nuevo it_ant. Dado que ejecutamos prim=it y it++, el inicio de la nueva escalera está en la posición anterior a it. En este caso res.first y res.second no cambian, porque la presente escalera solo contiene un elemento, y es seguro que existe una escalera anterior con un numero igual o mayor de elementos. Cota: La distancia entre it y v.end() decrece en cada iteración.