Cod sursa(job #1447822)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 5 iunie 2015 15:19:19
Problema Copii Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.82 kb
#include <cstdio>
#include <vector>
#include <set>

using namespace std;

const int Nmax = 20;

int n , i , j , echipe , ways;

char A[Nmax];

vector < int > g[Nmax] , v[Nmax];

set < int > prieteni;

void check(int nod)
{
    if (nod <= n)
    {
        /// bit 1 - se alatura la o echipa precedenta
        for (int i = 1; i <= echipe; ++i)
        {
            v[i].push_back(nod);
            check(nod + 1);
            v[i].pop_back();
        }

        /// bit 0 - echipa noua
        v[++echipe].push_back(nod);
        check(nod + 1);
        v[echipe--].pop_back();
    }
    else
    {
        bool NO = 0;

        if (echipe < 2)
            return;

        for (int ind = 1; ind <= echipe && !NO; ++ind)
        {
            ///multimea de prieteni ai echipei ind
            prieteni.clear();
            for (int i = 0; i < v[ind].size(); ++i)
            {
                int crt = v[ind][i];
                for (int j = 0; j < g[crt].size(); ++j)
                    prieteni.insert(g[crt][j]);
            }

            /// iau alta echipa si verific



            for (int i = 1; i <= echipe && !NO; ++i)
            {
                bool ok = false;

                for (int j = 0; j < v[i].size() && !ok && i != ind; ++j)
                    if (prieteni.find(v[i][j]) != prieteni.end())
                        ok = true;

                if (!ok && i != ind) NO = 1;
            }
        }

        if (!NO)
            ++ways;
    }
}

int main()
{
    freopen("copii.in","r",stdin);
    freopen("copii.out","w",stdout);

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

    for (i = 1; i <= n; ++i)
        for (gets(A+1), j = 1; j <= n; ++j)
            if (A[j] == '1')
                g[i].push_back(j);

    check(1);

    printf("%d\n", ways);

    return 0;
}