#include #include #include #include #include struct card { char rank; char color; bool used; }; int num_cards; int color_cnt[4]; int rank_cnt[13]; void marking_dfs(card from, std::vector& cards){ for (auto& c : cards){ if (c.used){ continue; } if (from.color == c.color || from.rank == c.rank){ c.used = true; marking_dfs(c, cards); } } } inline int color2idx(char c){ switch(c){ case 'C': return 0; case 'D': return 1; case 'H': return 2; case 'S': return 3; } } inline int& color_count(char c){ return color_cnt[color2idx(c)]; } inline int rank2idx(char c){ switch(c){ case 'A': return 0; case '2': return 1; case '3': return 2; case '4': return 3; case '5': return 4; case '6': return 5; case '7': return 6; case '8': return 7; case '9': return 8; case 'X': return 9; case 'J': return 10; case 'Q': return 11; case 'K': return 12; } } inline int& rank_count(char c){ return rank_cnt[rank2idx(c)]; } bool try_next(card last, std::vector& cards) { if (num_cards == 0) return true; for (auto& c : cards){ if (c.used){ continue; } if (last.color == 0 || c.color == last.color || c.rank == last.rank) { color_count(c.color)--; rank_count(c.rank)--; c.used = true; num_cards--; if (try_next(c, cards)) return true; num_cards++; c.used = false; rank_count(c.rank)++; color_count(c.color)++; } } return false; } int main() { std::ios_base::sync_with_stdio(false); int n; while (std::cin >> n) { // std::cerr << "reading " << n << " cards\n"; std::vector cards; std::memset(rank_cnt, 0, sizeof(rank_cnt)); std::memset(color_cnt, 0, sizeof(color_cnt)); std::string tmp; for (int i=0; i> tmp; // std::cerr << "read card #" << i << " as " << tmp[0] << tmp[1] << '\n'; auto color = tmp[1]; auto rank = tmp[0]; color_count(color)++; rank_count(rank)++; cards.push_back({rank, color, false}); } std::sort(cards.begin(), cards.begin() + 1, [](const card& l, const card& r){ auto l_possible = color_count(l.color) + rank_count(l.rank); auto r_possible = color_count(r.color) + rank_count(r.rank); return l_possible < r_possible; }); num_cards = n; // Boundary conditions // std::cerr << "Checking first boundary condition\n"; if (n == 1 || n > 37){ std::cout << "YES\n"; continue; } // std::cerr << "Checking second boundary condition\n"; bool possible = true; int how_many_low_level = 0; for (auto& c : cards){\ // std::cerr << "Checking card " << c.rank << ' ' << c.color << '\n'; // std::cout << rank_count(c.rank) << " " << color_count(c.color) << '\n'; if (color_count(c.color) == 1 && rank_count(c.rank) == 1){ // std::cout << "Singularity\n"; possible = false; break; } if (color_count(c.color) + rank_count(c.rank) == 3){ how_many_low_level++; } if (how_many_low_level > 2){ possible = false; break; } } cards[0].used = true; marking_dfs(cards[0], cards); for (auto& c : cards){ if (!c.used){ possible = false; break; } c.used = false; } if (possible && try_next({0, 0, true}, cards)){ std::cout << "YES\n"; } else { std::cout << "NO\n"; } } return 0; }