#include #include #include #include #include #include #include #include using namespace std; const float TIME_LIMIT = 2.85; const int STRLEN = 27; const int MAX_N = 201; const int START_L = 12; // 0-based const int START_R = 16; // 0-based const int POPULATION_SIZE = 400; const int RECOMBINATIONS_PER_CYCLE = 5; const int MUTATIONS_PER_CYCLE = 600; const double MAX_MUTATIONS_AT_A_TIME = 5; struct solution; float calc_dist(int, int); int n; char inputStr[MAX_N]; int dist[STRLEN][STRLEN]; vector population; template S& Container(priority_queue& q) { struct HackedQueue : private priority_queue { static S& Container(priority_queue& q) { return q.*&HackedQueue::c; } }; return HackedQueue::Container(q); } struct solution { char str[STRLEN]; int l, r; int score; solution() { l = START_L; r = START_R; } void reeval() { float result = 0; int l = this->l; int r = this->r; for (int i = 0; i < n; i++) { char ch = inputStr[i]; int pos = strchr(str, ch) - str; float ldist = calc_dist(l, pos); float rdist = calc_dist(r, pos); // TODO restrict by x coord if (ldist <= rdist) { result += ldist; l = pos; } else { result += rdist; r = pos; } } score = round(result); } }; bool operator<(const solution& a, const solution& b) { return a.score < b.score; } float calc_dist(int from, int to) { if (from <= to) { return dist[from][to]; } else { return dist[to][from]; } } int random(int exclusiveMax) { return rand() % exclusiveMax; } solution random_solution() { string str = "abcdefghijklmnopqrstuvwxyz"; random_shuffle(str.begin(), str.end()); solution res; for (int i = 0; i < STRLEN - 1; i++) { res.str[i] = str[i]; } res.str[STRLEN - 1] = '\0'; res.reeval(); return res; } solution mutate(const solution& sol) { solution result; for (int i = 0; i < STRLEN; i++) { result.str[i] = sol.str[i]; } int mutations = min(MAX_MUTATIONS_AT_A_TIME, TIME_LIMIT / ((clock() - 0.0) / CLOCKS_PER_SEC)); for (int i = 0; i < mutations; i++) { int p1 = random(STRLEN - 1); int p2 = random(STRLEN - 1); char c = result.str[p1]; result.str[p1] = result.str[p2]; result.str[p2] = c; } result.reeval(); return result; } solution cross(const solution &sol1, const solution &sol2) { solution result; int pos = STRLEN / 2; bool taken[STRLEN] = {}; for (int i = 0; i < pos; i++) { result.str[i] = sol1.str[i]; taken[result.str[i] - 'a'] = true; } for (int i = 0; i < STRLEN; i++) { char ch = sol2.str[i]; if (!taken[ch - 'a']) { result.str[pos++] = ch; } } result.str[STRLEN - 1] = '\0'; result.reeval(); return result; } void scan() { scanf("%d", &n); scanf("%s", inputStr); } void print() { sort(population.begin(), population.end()); solution sol = population[0]; printf("%s\n", sol.str); printf("%d %d\n", sol.l + 1, sol.r + 1); //printf("%d %d %d\n", sol.l + 1, sol.r + 1, sol.score); } void check_time() { if ((clock() - 0.0) / CLOCKS_PER_SEC > TIME_LIMIT) { print(); exit(0); }; } void init_dist() { const int h_offset = 38; const int v_offset_12 = 38; const int v_offset_23 = 40; const int h_offset_12 = 10; const int h_offset_23 = 27; const int break1 = 10; // 1-based const int break2 = 19; // 1-based float h_dist; float v_dist; for (int i = 0; i < STRLEN; i++) { for (int j = i; j < STRLEN; j++) { h_dist = 0; v_dist = 0; if (i < break1 && j >= break1 && j < break2) { h_dist = abs(i*h_offset - (h_offset_12 + (j - break1)*h_offset)); v_dist = v_offset_12; } else if (i >= break1 && i < break2 && j >= break2) { h_dist = abs((i - break1)*h_offset - (h_offset_23 + (j - break2)*h_offset)); v_dist = v_offset_12; } else if (i < break1 && j >= break2) { h_dist = abs(i*h_offset - (h_offset_12 + h_offset_23 + (j - break2)*h_offset)); v_dist = v_offset_12 + v_offset_23; } else { h_dist = (j - i) * h_offset; } dist[i][j] = round(sqrt(pow(h_dist, 2) + pow(v_dist, 2))); } } } void init_population() { for (int i = 0; i < POPULATION_SIZE; i++) { population.push_back(random_solution()); } } void evolve() { int size = population.size(); for (int i = 0; i < RECOMBINATIONS_PER_CYCLE; i++) { check_time(); solution a = population[random(size)]; solution b = population[random(size)]; solution child = cross(a, b); population.push_back(child); } for (int i = 0; i < MUTATIONS_PER_CYCLE; i++) { check_time(); solution mutated = mutate(population[random(size)]); population.push_back(mutated); } sort(population.begin(), population.end()); while (population.size() > POPULATION_SIZE) { population.pop_back(); } } void solve() { scan(); init_dist(); init_population(); while (true) { evolve(); } } int main() { freopen("keyboard.in", "r", stdin); freopen("keyboard.out", "w", stdout); solve(); return 0; }