Cod sursa(job #2007315)

Utilizator Coroian_DavidCoroian David Coroian_David Data 2 august 2017 14:56:04
Problema Fractal Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.39 kb
#include <cstdio>

#include <map>

#include <cassert>

using namespace std;

FILE *f, *g;

map <pair<pair<pair<pair<int, int>, int>, int>, int>, int>rez;

int k, x, y;

void readFile()
{
    f = fopen("fractal.in", "r");

    fscanf(f, "%d%d%d", &k, &y, &x);

    fclose(f);
}

int rezz;

int getZona(int x1, int y1, int p2)
{
    if(x1 > p2 && y1 > p2)
        return 3;

    if(x1 > p2 && y1 <= p2)
        return 2;

    if(x1 <= p2 && y1 > p2)
        return 4;

    if(x1 <= p2 && y1 <= p2)
        return 1;

    assert(1 == 0);

    return 0;
}

const int l[] = {0, 0, 1, 1, 0};
const int c[] = {0, 0, 0, 1, 1};

void to1(int &l, int &c, int p2)
{
    int aux = c;
    c = p2 - l + 1;
    l = aux;
}

void to4(int &l, int &c, int p2)
{
    int aux = c;
    c = l;
    l = p2 - aux + 1;
}

int drum(int k, int x1, int y1, int x2, int y2);

int APEL =0 ;

struct vv
{
    int x1, x2, y1, y2;
    int k, z1,z2;
};

vv calc[10009];

int drumuri(int k, int x1, int y1, int x2, int y2, int z1, int z2)
{

    calc[APEL + 1].x1 = x1;
    calc[APEL + 1].x2 = x2;
    calc[APEL + 1].y1 = y1;
    calc[APEL + 1].y2 = y2;
    calc[APEL + 1].k = k;
    calc[APEL + 1].z1 = z1;
    calc[APEL + 1].z2 = z2;

    APEL ++;

    int p2 = (1 << (k - 1));

    int z3 = getZona(x1, y1, p2);
    int z4 = getZona(x2, y2, p2);


    assert(x1 > 0 && y1 > 0 && x2 > 0 && y2 > 0);

    int pp = (1 << k)+1;

    assert(x1 < pp && y1 < pp && x2 < pp && y2 < pp);

    if(z1 != z3 || z2 != z4 || z3 > z4)
    {
        int eroare = 1;
        while(eroare)
        {
            printf("ERROR!!!\n");
        }
    }

  //  printf("DRUMURI K=%d c1: %d %d c2: %d %d z: %d %d, %d %d\n", k, x1, y1, x2, y2, z1, z2, z3, z4);

    if(rez[{{{{k, x1}, y1}, x2}, y2}] != 0)
        return rez[{{{{k, x1}, y1}, x2}, y2}];

    int ox1 = x1;
    int ox2 = x2;
    int oy1 = y1;
    int oy2 = y2;

    if(z1 == 2 && z2 == 3)
    {
        int midx1 = p2 + 1;
        int midy1 = p2;

        int midx2 = p2 + 1;
        int midy2 = p2 + 1;

        return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = 1 + drum(k - 1, x1 - p2, y1, midx1 - p2, midy1) + drum(k - 1, x2 - p2, y2 - p2, midx2 - p2, midy2 - p2);
    }

    if(z1 == 1 && z2 == 2)
    {
        int midx1 = p2;
        int midy1 = 1;

        int midx2 = p2 + 1;
        int midy2 = 1;

        to1(midx1, midy1, p2);
        to1(x1, y1, p2);

  //  printf("DRUMURIIIIIIIII K=%d c1: %d %d c2: %d %d z: %d %d, \n", k, x1, y1, x2, y2, z1, z2);
        return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = 1 + drum(k - 1, x1, y1, midx1, midy1) + drum(k - 1, x2 - p2, y2, midx2 - p2, midy2);
    }

    if(z1 == 3 && z2 == 4)
    {
        int midx1 = p2 + 1;
        int midy1 = p2 * 2;

        int midx2 = p2;
        int midy2 = p2 * 2;///<< 1

        to4(midx2, midy2, p2 * 2);
        to4(x2, y2, p2 * 2);

        return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = 1 + drum(k - 1, x1 - p2, y1 - p2, midx1 - p2, midy1 - p2) + drum(k - 1, x2, y2 /*- p2*/, midx2, midy2 /*- p2*/);
    }

    if(z1 == 1 && z2 == 4)
    {
        int midx1 = p2 + 1;
        int midy1 = 1;

        int midx2 = p2 * 2;
        int midy2 = p2 * 2;

       // printf("%d %d <= %d, %d\n", midx2, midy2,1 << k, getZona(midx2, midy2, p2));

        return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = drumuri(k, x1, y1, midx1, midy1, 1,2) + drumuri(k, midx1, midy1, midx2, midy2, 2, 3) + drumuri(k, midx2, midy2, x2, y2, 3, 4);
    }

    if(z1 == 2 && z2 == 4)
    {
        int midx2 = p2 * 2;
        int midy2 = p2 * 2;

        return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = drumuri(k, x1, y1, midx2, midy2, 2, 3) + drumuri(k, midx2, midy2, x2, y2, 3, 4);
    }

    if(z1 == 1 && z2 == 3)
    {
        int midx1 = p2 + 1;
        int midy1 = 1;

        return rez[{{{{k, ox1}, oy1}, ox2}, oy2}] = drumuri(k, x1, y1, midx1, midy1, 1,2) + drumuri(k, midx1, midy1, x2, y2, 2, 3);
    }

    assert(1 == 0);

    return 0;
}

void schimba(int &a, int &b)
{
    int aux = a;
    a = b;
    b = aux;
}

int drum(int k, int x1, int y1, int x2, int y2)
{
   // APEL++;

   // printf("K=%d c1: %d %d c2: %d %d\n", k, x1, y1, x2, y2);

    assert(x1 > 0 && y1 > 0 && x2 > 0 && y2 > 0);

    int pp = (1 << k)+1;

    assert(x1 < pp && y1 < pp && x2 < pp && y2 < pp);

    if(x1 == x2 && y1 == y2){//printf("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO %d %d %d %d\n", x1, x2, y1, y2);
        return 0;}

    if(k == 1)
    {
        if(x1 == 1 && x2 == 1)
            return 3;

        if(x1 == 2 && x2 == 2)
            return 1;

        if(y1 == y2)
            return 1;

        return 2;
    }

    if(rez[{{{{k, x1}, y1}, x2}, y2}] != 0)
        return rez[{{{{k, x1}, y1}, x2}, y2}];

    int p2 = (1 << (k - 1));

    int z1 = getZona(x1, y1, p2);
    int z2 = getZona(x2, y2, p2);


  //  printf("+++++++++K=%d c1: %d %d c2: %d %d z: %d %d\n", k, x1, y1, x2, y2, z1, z2);

    if(z1 > z2)
    {
        schimba(x1, x2);
        schimba(y1, y2);
        schimba(z1, z2);
    }



   // printf("+++++++++K=%d c1: %d %d c2: %d %d z: %d %d\n", k, x1, y1, x2, y2, z1, z2);

    if(z1 == z2)
    {
        if(z1 == 2 || z1 == 3)
            return rez[{{{{k, x1}, y1}, x2}, y2}] = drum(k - 1, x1 - p2 * l[z1], y1 - p2 * c[z1], x2 - p2 * l[z1], y2 - p2 * c[z1]);

        else
        {
            if(z1 == 1)
            {
                to1(x1, y1, p2);
                to1(x2, y2, p2);
            }

            if(z1 == 4)
            {
                to4(x1, y1, p2 * 2);
                to4(x2, y2, p2 * 2);
            }

            return rez[{{{{k, x1}, y1}, x2}, y2}] = drum(k - 1, x1, y1, x2, y2);
        }
    }

    return rez[{{{{k, x1}, y1}, x2}, y2}] = drumuri(k, x1, y1, x2, y2, z1, z2);
}

void solve()
{
    rezz = drum(k, 1, 1, x, y);

    /*printf("%d\n", APEL);

    for(int i = 1; i <= APEL; i ++)
    {

    printf("DRUMURI K=%d c1: %d %d c2: %d %d z: %d %d  = %d\n", calc[i].k, calc[i].x1, calc[i].y1, calc[i].x2, calc[i].y2, calc[i].z1, calc[i].z2, rez[{{{{calc[i].k, calc[i].x1}, calc[i].y1}, calc[i].x2}, calc[i].y2}]);
    }*/
}

void printFile()
{
    g = fopen("fractal.out", "w");

    assert(rezz >= 0);

    fprintf(g, "%d\n", rezz);

    fclose(g);
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}