/** * Use recursive backtracking to try assigning each letter balloon * to each team that has that letter as an initial. * This submission should get TLE. * Time complexity: O(t^p) */ fun main() { val (p, t) = readln().split(" ").map { it -> it.toInt() } val teams = Array(t) { readln().toCharArray().sortedArray() } // Discard any teams that have repeated characters. val filteredTeams = teams.filter { it -> for ((chIndex, ch) in it.withIndex()) { if (chIndex > 0 && it[chIndex - 1] == ch) { false } if (ch - 'A' >= p) { false } } true } var assignment = Array>(filteredTeams.size) { ArrayList() } val best = solve(p, filteredTeams, 0, assignment) println(best) } fun solve(numLetters: Int, teams: List, letter: Int, assignment: Array>): Int { if (letter == numLetters) { // Check which teams have all letters covered. var teamsCovered = 0 for (teamIndex in 0..teams.size - 1) { val team = teams[teamIndex] val balloons = assignment[teamIndex] var teamChIndex = 0 var balloonIndex = 0 while (teamChIndex < team.size && balloonIndex < balloons.size) { if (balloons[balloonIndex] == team[teamChIndex]) { teamChIndex++ balloonIndex++ } else { balloonIndex++ } } if (teamChIndex == team.size) { teamsCovered++ } } return teamsCovered } var best = 0 for (teamIndex in 0..teams.size - 1) { for (ch in teams[teamIndex]) { if (ch == 'A' + letter) { // Assign letter to team. assignment[teamIndex].add('A' + letter) val curr = solve(numLetters, teams, letter + 1, assignment) if (curr > best) { best = curr } // Unassign letter. assignment[teamIndex].removeAt(assignment[teamIndex].size - 1) } } } // Try not assigning the letter. val noAssignment = solve(numLetters, teams, letter + 1, assignment) if (noAssignment > best) { best = noAssignment } return best }