/* Utopia (IOI 2002) Copyright (C) 2002 Maurizio Sambati This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA È possibile ridurre la complessità del problema ad una sola dimensione. Quello che vogliamo dimostrare è che avendo una lista ordinata di numeri diversi (ovvero a1 < a2 < a3 < ... < an) è sempre possibile avere una soluzione. In questo modo è possibile riportare il problema a due dimensioni: semplicemente considereremo gli spostamenti nell'asse delle x e nell'asse delle y separatamente usando due liste ordinate separate di numeri. Considerando il problema solo sull'asse delle x abbiamo a che fare con soli due quadranti, uno negativo ed uno positivo. Se il nostro percorso semplicemente richiedesse di saltare da un quadrante all'altro non ci sarebbero problemi, sarebbe infatti sufficiente alternare il segno dei numeri estratti in ordine crescente dalla lista. La difficoltà ci viene incontro con le fermate. Nel nostro percorso, purtroppo, ci sono... Per scavalcare questo ostacolo spacchiamo in due la lista dei numeri. Prendiamo i primi k codici, con k uguale al numero di fermate, e teniamo i restanti n-k (n è il numero di codici che abbiamo a disposizione) per gli spostamenti normali (ovvero da un quadrante a quello opposto). Per fare ancora più confusione, chiameremo le due liste F e S, rispettivamente (entrambe le liste sono in ordine strettamente crescente). Procediamo quindi nel seguente modo: - se nel passo successivo del percorso dobbiamo cambiare quadrante estraiamo il primo codice dalla lista S, sistemiamo il segno come negativo se dobbiamo spostarci nel quadrante negativo, positivo altrimenti, e lo sommiamo alla posizione corrente (mandandolo ovviamente in output); - se dobbiamo mantenere la posizione all'interno del quadrante alterniamo il segno dei codici estratti da F (tenendo conto dell'ordine) e sommiamo il numero, così ottenuto, di conseguenza (notate che i segni devono essere alternati tenendo conto anche del quadrante che stiamo visitando: se l'ultimo movimento per tenere la posizione nel quadrante 1 è diretto verso l'interno e poi successivamente ci spostiamo nel quadrante 2, per tenere la fermata il segno del nuovo codice estratto da F deve permettere un movimento verso l'esterno). */ #include #include #include using namespace std; const int MAXN = 10000; int codici[MAXN*2]; int percorso[MAXN]; int N; int xfermate, yfermate; int *ycodici, *xcodici; inline void quadrante( int val, int &x, int &y ); void leggi(); void risolvi(); int main() { leggi(); risolvi(); } void leggi() { cin >> N; for( int i = 0; i < N*2; ++i ) { cin >> codici[i]; } xfermate = 0; yfermate = 0; int xprev = 0; int yprev = 0; for( int i = 0; i < N; ++i ) { cin >> percorso[i]; int xcurr, ycurr; quadrante( percorso[i], xcurr, ycurr ); if( xcurr == xprev ) ++xfermate; if( ycurr == yprev ) ++yfermate; xprev = xcurr; yprev = ycurr; } sort( codici, &codici[N*2] ); xcodici = &codici[0]; ycodici = &codici[N]; } // indica se gli assi di un certo quadrante sono positivi o negativi inline void quadrante( int val, int &x, int &y ) { static const int xval[] = { 0, 1, -1, -1, 1 }; static const int yval[] = { 0, 1, 1, -1, -1 }; assert( val >= 1 && val <= 4 ); x = xval[val]; y = yval[val]; } void risolvi() { int xmin = xfermate - 1; int xmax = xfermate; int ymin = yfermate - 1; int ymax = yfermate; int xprev = 0; int yprev = 0; int xflag, yflag; quadrante( percorso[0], xflag, yflag ); xflag = -xflag; yflag = -yflag; int x, y; x = y = 0; for( int i = 0; i < N; ++i ) { int xcurr, ycurr; int codx, cody; quadrante( percorso[i], xcurr, ycurr ); // si sposta lungo l'asse delle x if( xcurr != xprev ) { codx = xcodici[xmax++] * xcurr; } else { codx = xcodici[xmin--] * xflag; xflag = -xflag; } // si sposta lungo l'asse delle y if( ycurr != yprev ) { cody = ycodici[ymax++] * ycurr; } else { cody = ycodici[ymin--] * yflag; yflag = -yflag; } cout << codx << ' ' << cody << endl; x += codx; y += cody; assert( !( ( x * xcurr <= 0 ) || ( y * ycurr <= 0 ) ) ); xprev = xcurr; yprev = ycurr; } }