arc084_b (pensamiento + camino más corto) (buena pregunta)

tema

Portal

D -
Límite de tiempo múltiple pequeño : 2 segundos / Límite de memoria: 256 MB

Planteamiento del problema

Encuentre la suma más pequeña posible de los dígitos en la notación decimal de un múltiplo positivo de K.

Restricciones

2≤K≤105
K es un número entero.

Entrada

La entrada se proporciona desde la entrada estándar en el siguiente formato:
K

Salida

Imprima la suma más pequeña posible de los dígitos en la notación decimal de un múltiplo positivo de K.
Muestras

Entrada Salida Declaración
6 3 12 = 6 × 2 da como resultado la suma más pequeña
41 5 11111 = 41 × 271 da como resultado la suma más pequeña
79992 36

análisis

  • El significado de la pregunta es dar un número k y preguntarle cuál es la suma más pequeña de cada dígito (en sistema decimal) entre los múltiplos enteros positivos.
  • Esta pregunta también es una buena pregunta para encontrar el camino más corto a través del dibujo.
  • Cree un nuevo gráfico con k nodos en total, que represente el valor obtenido módulo k.
  • Primero puede construir un mapa, basado en el lado de construcción de un número conocido x%k=p, luego obtener y más detrás del dígito x, puede conocer claramente y%kel valor, por lo que obtuvo un mapa, además de representantes de cada lado de la parte posterior Uno, Bian Quan es este número.
  • Lado de ejecución más corto, donde el número de dis [i] significado es más que k i-mode en cada uno de los mínimos y cuánto, para comenzar 1~9todos se unen a la cola (que para la primera lata), ejecutándose una vez SPFA, la salida final dis [ 0] OK.

programa

#include <cstdio>
#include <cstring>
#define For(x) for(int h=head[x],o=V[h],w=W[h]; h; o=V[h=to[h]],w=W[h])
using namespace std;
int head[100005],to[1000005],V[1000005],W[1000005],num;
int q[10000005],l,r,f[100005],dis[100005];
int k;
void Add(int x,int y,int z){
    to[++num]=head[x],head[x]=num,V[num]=y,W[num]=z;
}

void SPFA(){
    memset(dis,0x7f,sizeof(dis));
    for (int i=1; i<10; i++) q[++r]=dis[i]=f[i]=i;      //起始位(及最终数的最高位)是 1~9 都可以,都要加入队列中 
    for (l=1; l<=r; l++){
        For(q[l]) if (dis[o]>dis[q[l]]+w){
            dis[o]=dis[q[l]]+w;
            if (!f[o]){
                f[o]=1;
                q[++r]=o;
            }
        }
        f[q[l]]=0;
    }
}

void debug(){
    for (int i=0; i<k; i++){
        printf("%d\t",i);
        For(i) printf("(%d %d) ",o,w);
        puts("");
    }
    puts("");
}

int main(){
    scanf("%d",&k);
    for (int i=1; i<k; i++)
        for (int j=0; j<10; j++)
            Add(i,(i*10+j)%k,j);        //每个模数往后加一个位(0~9都可),可以形成一个到另一个模数的边 
    SPFA();
    printf("%d",dis[0]);                //通过重重操作,最后得到模数为 0 (k的正整数倍)的路径长就是每一位的和 
}

Supongo que te gusta

Origin blog.csdn.net/jackypigpig/article/details/78471826
Recomendado
Clasificación