Cod sursa(job #2035178)

Utilizator mariusn01Marius Nicoli mariusn01 Data 9 octombrie 2017 00:15:10
Problema Ghiozdan Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.91 kb
#include <fstream>
#define DIM 75010
#define INF 1000000000
  
using namespace std;
ifstream fin("ghiozdan.in");
ofstream fout("ghiozdan.out");
  
  
int F[210];
int D[2][DIM];
  
//D[i][j] = numarul minim de obiecte pentru a obtine greutatea j
//luand in calcul doar greutatile <= i
int Q[DIM];
  
int T[2][DIM];
// T[i][j] = obtin D[i][j] dar sigur am inclusa aici greutatea T[i][j] doar cu greutati
// din prima jumatate a intervalului st, dr (deci, restul pana la greutatea j folosesc
// greutati din a doua jumatate a intervalului st, dr)

  
  
int N, G, i, j, r, x, p, u, step, act;
  
void rec(int st, int dr, int G) {
    int i;
    if (G==0)
        return;
  
    if (st == dr){
        int nr;
  
        for (nr = 1; nr <= F[st] && G - st >= 0; nr++){
            fout<<st<<"\n";
            G = G - st;
        }
        return;
    }
  
  
    int mid = (dr + st)/2;
  
  
    for (i=0;i<=1;i++)
        for (j=0;j<=G;j++)
            D[i][j] = INF;
    D[0][0] = 0;
    act = 1;
  
    for (i=st;i<=dr;i++) {
        if (F[i] == 0)
            continue;
  
        D[0][0] = 0;
        D[1][0] = 0;
  
        for (r=i; r>=1; r--) {
            //calculez D[i][j] cu j de forma multiplu de i + r
            p = 1; u = 0;
  
  
            for (j=r; j<=G; j+=i) {
  
                D[act][j] = D[!act][j];
  
                if (D[act][j] != INF){
                    if (i <= mid)
                        T[act][j] = j;
                    else
                        T[act][j] = T[!act][j];
                    //T[act][j] = 0;
                }
  
                if (j-i >= 0 && D[!act][j-i] != INF) {
                    while (p<=u && D[!act][j-i] < D[!act][ Q[u] ] + (j-i-Q[u])/i) {
                        u--;
                    }
                    Q[++u] = j-i;
                }
  
                if ((j-Q[p])/i > F[i])
                    p++;
                if (p <= u) {
                    if (D[act][j] > D[!act][ Q[p] ] + ( j-Q[p] )/i) {
                        D[act][j] = D[!act][ Q[p] ] + ( j-Q[p] )/i;
                        if (i <= mid)
                            T[act][j] = j;
                        else
                            T[act][j] = T[!act][Q[p]];
                    }
                }
  
            }
  
        }
        act = !act;
    }
    int aux;
    for (i=G;i>=1;i--)
        if (D[!act][i] != INF) {
            aux = T[!act][i];
            break;
        }
  
  
    if (st == 1 && dr == 200) {
        fout<<i<<" "<<D[!act][i]<<"\n";
    }
  
    rec(st, mid, aux);
    rec(mid+1, dr, i-aux);
  
}
  
  
int main() {
    fin>>N>>G;
    for (i=1;i<=N;i++) {
        fin>>x;
        F[x]++;
    }
  
    rec(1, 200, G);
/*
    for (i=G; i>=1; i--)
        if (D[!act][i] != INF) {
            fout<<i<<" "<<D[!act][i];
            break;
        }
*/
    return 0;
}