1. Enumeración: 1753, 2965
2. Codicioso: 2109, 2586
3. Árbol de expansión mínimo: 2485, 1258
4. Clasificación: 2388
5. Búsqueda de optimización en profundidad: 1321, 2251
6. Búsqueda optimizada de amplitud: 3278, 1426
7. Técnicas de búsqueda simple y poda: 2676
8. El problema de la mochila: 1837
9. Clasificación topológica: 1094
10. Algoritmo de ruta más corta: 1062, 1125, 2240
11. Árbol de Huffman: 3253
12. Métodos de búsqueda eficientes como tabla hash y búsqueda binaria: 2151, 2503
Continúe practicando la enumeración esta semana.
Universidad de Pekín POJ2956: Números repetidos
tema
analizar
Entrada : el archivo de prueba de entrada contendrá varios casos de prueba, cada caso de prueba constará de una sola línea que contiene el número entero n , donde 1 ≤ n ≤ 1000000. El final del archivo está marcado por un caso de prueba con n = 0 y no debe procesarse.
Salida : para cada caso de entrada, el programa debe imprimir el n-ésimo número único en una línea .
Ejemplo de entrada:
25
10000
0
Salida de ejemplo:
27
26057
Mi línea de pensamiento:
Es una solución violenta, enumeración + clasificación para juzgar si se cumplen las condiciones.
Avanzado
1. Utilice BFS :
No esperaba usar BFS en absoluto.
——El estado inicial es 1~9, y el estado de la siguiente capa se puede obtener agregando continuamente 0~9 después del estado inicial, y el estado de la segunda capa se expande continuamente hasta que la expansión alcanza el estado 1000000. Cada estado contiene dos atributos value y digit, value es el valor del estado, asumiendo que es 134, entonces digit es 11010, d[i]=1 significa que i está en el valor, cuando el número 0~9 se agrega después el número 134 (Suponga que el número agregado es 1), cómo juzgar si 1 ha aparecido en 134, valor = 1, luego dígito = 10, y la operación de 11010 y 10 es 11010 y 10, si el resultado no es igual a 0, significa que 1 está en 134 existe, de lo contrario no existe.
2. Considere algunos casos para reducir la enumeración :
Cree una matriz, guarde cada bit y juzgue si hay números repetidos (aquí se parece un poco al almacenamiento de bits mencionado en el Capítulo 1). Por ejemplo, para un número 128267, su segundo dígito (contando de derecha a izquierda) es el mismo que el cuarto dígito, entonces el número en forma de 1282** no necesita enumerarse y puede enumerarse directamente desde 128300. Esto acelera el tiempo de enumeración.
el código
1. Utilice BFS:
1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5
6 const int N = 1000000;
7 struct Number
8 {
9 int value; //数字的十进制表示
10 int digit; //二进制序列,从右往左数digit[i]==1表示value中有i
11
12 Number(){}
13 Number(int v, int d):value(v), digit(d){}
14 }ans[N+10];
15
16 int main()
17 {
18 for(int i=1; i<10; i++)
19 ans[i] = Number(i, 1<<i);
20
21 int k = 1;
22 for(int cur=10; cur<=N; k++)
23 {
24 int v = ans[k].value;
25 int d = ans[k].digit;
26
27 for(int i=0; i<10; i++)
28 {
29 if( !(d & (1<<i)))
30 ans[cur++] = Number(v*10+i, d|1<<i);
31 }
32 }
33
34 int n;
35 while(scanf("%d", &n)==1 && n)
36 printf("%d\n", ans[n].value);
37 return 0;
38 }
2. Reducir la enumeración:
1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5
6 const int N = 1000000;
7 int ans[N+1] = {0};
8 int power[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
9
10 void init()
11 {
12 int d[10]; //存储数字x
13 int v[10]; //v[i]表示数字i是否在x中出现过
14 int cur = 1;
15 int x, y=1;
16 while(cur<=N)
17 {
18 x = y;
19 memset(v, -1, sizeof(v));
20 memset(d, 0, sizeof(d));
21
22 int i, j;
23 for(i=0; x!=0; i++)
24 {
25 d[i] = x % 10;
26 if(v[d[i]]!=-1)
27 break;
28 v[d[i]] = i;
29 x /= 10;
30 }
31 if(!x)
32 {
33 ans[cur++] = y;
34 y++;
35 }
36 else
37 {
38 j = v[d[i]];
39 for(i--; i>=j; i--)
40 x = x*10+d[i];
41 x++;
42 y = x*power[j];
43 }
44 }
45 }
46
47 int main()
48 {
49 init();
50 int n;
51 while(cin>>n && n)
52 cout<<ans[n]<<endl;
53 return 0;
54 }