Submission #497286

#TimeUsernameProblemLanguageResultExecution timeMemory
497286OzyParrots (IOI11_parrots)C++17
99 / 100
6 ms1316 KiB
#include "encoder.h" #include "encoderlib.h" #include <iostream> #include <vector> using namespace std; #define lli long long #define MAXN 22 lli dp[MAXN][MAXN]; void llena_tabla(){ // Voy a llenar la tabla dinámica de caminos desde el final (16, 20) hacia el inicio (0,0). // es una tabla dinámica normal en que te puedes mover a la izquierda y abajo en este caso. // La inicialización es que la fila de arriba y la columna de la derecha sólo tienen un camino. for(int fil = 0; fil <= 16; ++fil) dp[fil][20] = 1; for(int col = 0; col <= 20; ++col) dp[16][col] = 1; // Luego hay que llenar la tabla // Los lugares van de 0 a 20 porque voy a dividir en grupos de 4 números entonces puedo enviar 20 pericos por cada grupo. for(int col = 19; col >= 0; --col){ // Las filas representan los valores, van del 0 al 16 porque el 0 significa que no esta y luego son los valores de 0 a 15 // uso solo valores de 0 a 15 porque voy a usar 4 bits para indicar el grupo al que pertenece el número y // 4 bits para el valor en sí, entonces sólo podré poner valores de 0 a 15. for(int fil = 15; fil >= 0; --fil){ dp[fil][col] = dp[fil + 1][col] + dp[fil][col + 1]; } } } vector<int> construye_secuencia(lli grupo, lli cuatroNumeros){ int valor = 0; // Esta variable lleva el número de la secuencia. int fil = 0, col = 0; // Llevan la posición en la tabla dinámica. vector<int> res; // Para construir la secuencia será necesario fijarse en la tabla de caminos. // Si moviéndose a la derecha hay suficientes caminos para llegar al número que se requiere, // entonces hay que moverse a la derecha. En caso contrario hay que moverse hacia arriba (avanzando un valor) // y tomando en cuenta todas las opciones que se hubieran usado si se movia a la derecha. while (fil < 16 || col < 20){ if (dp[fil][col + 1] >= cuatroNumeros){ // Hay suficientes opciones sin avanzar de numero col++; if (fil) res.push_back((grupo << 4) + fil - 1); } else{ // No hay suficientes caminos avanzando a la derecha, hay que aumentar de número cuatroNumeros -= dp[fil][col + 1]; fil++; } } return res; } void encode(int N, int M[]) { // Construye la tabla de caminos llena_tabla(); // Haz grupos de 4 números lli cuatroNumeros; lli grupo = 0, pos = 0; while (pos < N){ cuatroNumeros = 0; for(int i = 0; i <= 3; ++i){ cuatroNumeros <<= 8; // recorrelo 8 lugares para hacer lugar al nuevo if (pos < N) cuatroNumeros += M[pos++]; // agregale el nuevo número e incrementa la posición. } // construye la secuencia y enviala vector<int> secuencia = construye_secuencia(grupo, cuatroNumeros + 1); for(auto s : secuencia) send(s); ++grupo; // avanza al siguiente grupo. } }
#include "decoder.h" #include "decoderlib.h" #include <iostream> #include <vector> #include <algorithm> using namespace std; #define lli long long #define MAXN 22 lli dp_dec[MAXN][MAXN]; void llena_tabla_dec(){ for(int fil = 0; fil <= 16; ++fil) dp_dec[fil][20] = 1; for(int col = 0; col <= 20; ++col) dp_dec[16][col] = 1; for(int col = 19; col >= 0; --col) for(int fil = 15; fil >= 0; --fil) dp_dec[fil][col] = dp_dec[fil + 1][col] + dp_dec[fil][col + 1]; } lli construye_numero(vector<int> &secuencia){ int fil = 0, col = 0; // Llevan la posición en la tabla dinámica. lli res = 0; // Primero hay que normalizar la secuencia. Hay que sumarle 1 a cada número para // que estén en el rango [1, 16] y agregarle 0's si le faltan posiciones. for(int i = 0; i < secuencia.size(); ++i) secuencia[i]++; while (secuencia.size() < 20) secuencia.push_back(0); // Después hay que ordenar la secuencia sort(secuencia.begin(), secuencia.end()); // Finalmente, para reconstruir el número a partir de la secuencia de nuevo se usa // la tabla dinámica pero esta vez sumando los caminos que se van dejando sin usar. lli valorprev = 0; // Esta variable es para saber si cambia el valor. for(int i = 0; i < 20; ++i){ if (secuencia[i] != valorprev){ while (fil < secuencia[i]) { res += dp_dec[fil][col + 1]; ++fil; } valorprev = secuencia[i]; } ++col; } return res; } void decode(int N, int L, int X[]) { llena_tabla_dec(); vector<int> mensaje; vector<vector<int> > secuencia(16); lli grupo, valor, pos; // Para cada perico del mensaje obten el valor y el grupo al que pertenece. // Agrega el valor a la secuencia de ese grupo para luego ordenar y reconstruir. for(int i = 0; i < L; ++i){ grupo = X[i] >> 4; valor = X[i] & 15; secuencia[grupo].push_back(valor); } // Decodifica cada secuencia para generar los números lli cuatroNumeros; pos = 0; for(int i = 0; i < 16; ++i){ cuatroNumeros = construye_numero(secuencia[i]); for(int j = 0; j <= 3; ++j) if (pos < N){ mensaje.push_back((cuatroNumeros & 0xFF000000) >> 24); // Escribe el último número cuatroNumeros <<= 8; // recorre el numero para el siguiente byte. ++pos; } if (pos >= N) break; } for(auto n : mensaje) output(n); }

Compilation message (stderr)

encoder.cpp: In function 'std::vector<int> construye_secuencia(long long int, long long int)':
encoder.cpp:34:9: warning: unused variable 'valor' [-Wunused-variable]
   34 |     int valor = 0; // Esta variable lleva el número de la secuencia.
      |         ^~~~~

decoder.cpp: In function 'long long int construye_numero(std::vector<int>&)':
decoder.cpp:29:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   29 |     for(int i = 0; i < secuencia.size(); ++i) secuencia[i]++;
      |                    ~~^~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...