Cod sursa(job #20190)

Utilizator astronomyAirinei Adrian astronomy Data 20 februarie 2007 20:21:48
Problema Ghiozdan Scor 100
Compilator c Status done
Runda Arhiva de probleme Marime 2.25 kb
#include <stdio.h>

#define INF 1000000000
#define MAXG 76000
#define MAXVAL 256
#define mid ((st+dr)>>1)

int N, G, Gmax, Nmin, V[MAXVAL], Min[2][MAXG];

int Q[MAXG], Pos[MAXG];

int A[2][MAXG], cnt[MAXVAL];

void solve(int st, int dr, int H, int ind)
{
    int i, t, k, g, p, u = 0, v = 1, inc, sf;

    for(g = 1; g <= H; g++)
        Min[u][g] = INF;
    Min[u][0] = 0;

    for(i = st; i <= dr; i++)
     if(V[i])
     {
        for(k = 0; k < i; k++)
        {
            Q[inc = sf = 0] = Min[u][k], Pos[0] = 0;
            for(t = 0, p = k; p <= H; p += i, t++)
            {
                Min[v][p] = Min[u][p];

                for(; Min[u][p] <= Q[sf]+(t-Pos[sf]) && sf >= inc; sf--) ;

                Q[++sf] = Min[u][p], Pos[sf] = t;

                if(t-Pos[inc] > V[i])
                    inc++;
                    
                if(Min[v][p] > Q[inc]+t-Pos[inc])
                    Min[v][p] = Q[inc]+t-Pos[inc];
            }
        }
        u ^= 1, v ^= 1;
     }


    if(ind == -1)
    {
        for(g = G; g >= 0; g--)
         if(Min[u][g] < INF)
         {
            Gmax = g, Nmin = Min[u][g];
            break ;
         }
    }
    else
        for(g = 0; g <= H; g++)
            A[ind][g] = Min[u][g];
}

void baga(int st, int dr, int H, int nrmin)
{
    int X, t1, t2;

    if(st == dr)
    {
        cnt[st] = H/st;
        return ;
    }

    solve(st, mid, H, 0), solve(mid+1, dr, H, 1);

    for(X = 0; X <= H; X++)
     if(A[0][X]+A[1][H-X] == nrmin)
     {
        t1 = A[0][X], t2 = A[1][H-X];
        baga(st, mid, X, t1), baga(mid+1, dr, H-X, t2);
        return ;
     }
}

void read_data(void)
{
    int i, v;

    scanf("%d %d\n", &N, &G);

    for(i = 1; i <= N; i++)
        scanf("%d\n", &v), V[v]++;
}

void write_data(void)
{
    int i, j;

    printf("%d %d\n", Gmax, Nmin);
    for(i = 1; i <= 200; i++)
     for(j = 1; j <= cnt[i]; j++)
        printf("%d\n", i);
}

int main(void)
{
    freopen("ghiozdan.in", "rt", stdin);
    freopen("ghiozdan.out", "wt", stdout);

    read_data();
    solve(1, 200, G, -1);
    baga(1, 200, Gmax, Nmin);
    write_data();

    return 0;
}