//package worldcodesprint12; import java.io.*; import java.util.*; import java.text.*; import java.math.*; import java.util.regex.*; /** * * link to problem: * https://www.hackerrank.com/contests/world-codesprint-12/challenges/animal-transport * * * He must visit the zoos in increasing order. Dogs are scared of elephants, so * he is not allowed to bring them together at the same time. Cats are scared of * dogs, so he is not allowed to bring them together at the same time. Mice are * scared of cats, so he is not allowed to bring them together at the same time. * Elephants are scared of mice, so he is not allowed to bring them together at * the same time. * * minimum zoo number that must be reached in order to transport animals * */ public class AnimalTransport { static boolean debug = false; StringBuilder sb = new StringBuilder(); int m, n; char[] animalType; int[] zooSource; int[] zooDest; List animals; TreeSet zooDestIndexes; public static void main(String[] args) { new AnimalTransport().solve(); } private void solve() { //input Scanner in = new Scanner(System.in); int t = in.nextInt(); for (int i = 0; i < t; i++) { m = in.nextInt(); n = in.nextInt(); animalType = new char[n]; zooSource = new int[n]; zooDest = new int[n]; for (int j = 0; j < n; j++) { animalType[j] = in.next().charAt(0); } for (int j = 0; j < n; j++) { zooSource[j] = in.nextInt(); } for (int j = 0; j < n; j++) { zooDest[j] = in.nextInt(); } animals = new ArrayList<>(); for (int j = 0; j < n; j++) { animals.add(new Animal(animalType[j], zooSource[j], zooDest[j])); } if (debug) { System.out.println("animals=" + animals); } //find path for 1..n animals for (int target = 1; target <= n; target++) { zooDestIndexes = new TreeSet<>(); minimumZooNumbers(target, new TreeSet(), new TreeSet()); if (debug) { System.out.println("zooDestIndexes=" + zooDestIndexes); } int zoo = -1; zooDestIndexes.remove(zoo); //first is -1 if (!zooDestIndexes.isEmpty()) { zoo = zooDestIndexes.first(); if (debug) { System.out.println("result zoo=" + zoo); System.out.println(""); } } sb.append(zoo).append(" "); } sb.append("\n"); } System.out.print(sb.toString()); } private void minimumZooNumbers(final int target, Set used, Set delivered) { for (int i = 0; i < n; i++) { if (used.size() + delivered.size() == target) { int zoo = getLargestZooDest(used, delivered); zooDestIndexes.add(zoo); if (debug) { System.out.println("found!"); System.out.println("target=" + target); System.out.println("zoo=" + zoo); System.out.println("zooDestIndexes in minimumZooNumbers=" + zooDestIndexes); } return; } if (available(i, used) && available(i, delivered) && sourceLessDest(i) && !conflict(i, used) && !goBack(i, delivered)) { //take animal if (debug) { System.out.println("take=" + animals.get(i)); } Set used2 = new TreeSet<>(used); used2.add(i); Set delivered2 = new TreeSet<>(delivered); //deliver deliver(i, used2, delivered2); if (debug) { System.out.println("used =" + used2); System.out.println("dest=" + animals.get(i)); } //try more animals minimumZooNumbers(target, used2, delivered2); } } } private boolean available(int i, Set set) { return !set.contains(i); } private boolean sourceLessDest(int i) { if (zooSource[i] < zooDest[i]) { return true; } if (zooSource[i] == zooDest[i]) { throw new IllegalStateException("" + i); } return false; } private boolean conflict(int i, Set used) { char type1 = animalType[i]; for (Integer ind : used) { char type2 = animalType[ind]; if (zooDest[i] <= zooSource[ind]) { //fix issue: //E D C M //1 1 1 2 //2 2 2 4 continue; } if (conflict(type1, type2) || conflict(type2, type1)) { return true; } } return false; } private void deliver(int i, Set used, Set delivered) { int till = zooSource[i]; //iterate over a copy for (Integer ind : new TreeSet<>(used)) { if (zooDest[ind] <= till) { delivered.add(ind); used.remove(ind); } } } private int getLargestZooDest(Set used, Set delivered) { int zoo = -1; if (debug) { System.out.println("used =" + used); System.out.println("deliv=" + delivered); } for (Integer ind : used) { if (zooDest[ind] > zoo) { zoo = zooDest[ind]; } } for (Integer ind : delivered) { if (zooDest[ind] > zoo) { zoo = zooDest[ind]; } } return zoo; } private boolean conflict(char t1, char t2) { if (t1 == 'D' && t2 == 'E') { return true; } if (t1 == 'C' && t2 == 'D') { return true; } if (t1 == 'M' && t2 == 'C') { return true; } if (t1 == 'E' && t2 == 'M') { return true; } return false; } private boolean goBack(int i, Set delivered) { int source = zooSource[i]; for (Integer ind : delivered) { if (zooDest[ind] > source) { return true; } } return false; } } class Animal { char type; int source, dest; public Animal(char type, int source, int dest) { this.type = type; this.source = source; this.dest = dest; } @Override public String toString() { return "(" + "t=" + type + ", s=" + source + ", d=" + dest + ')'; } }