În Regatul din Sud nu e niciodată prea devreme să te pregăteşti de război. De aceea, în fiecare an Regele organizează un concurs în care premiaţi sunt cei mai buni strategi. Mai întâi, Strategul Şef alege configuraţia ideală de razboi, în care armata va fi dispusă. O trupă într-o configurație e reprezentată de o literă mica din mulțimea {'a'..'z'}
. De exemplu, configuraţia “ffscaam"
descrie o armată formată din doi fermieri, un soldat, un cavaler, doi arcaşi şi un mag. Bineînţeles, în timpul unei lupte, trupele nu îşi vor menţine neapărat poziiţile inţiale. Cu toate acestea, orice tip de trupă poate schimba poziţia cu maxim un alt tip de trupă, ştiut de dinainte de toţi locuitorii regatului. De asemenea se ştie că arcaşii nu schimbă poziţii decât între ei. Pentru exemplul anterior, dacă un fermier sau un soldat nu schimbă poziţii decât cu un alt fermier sau soldat, configuraţii echivalente cu “ffscaam"
sunt “fsfcaam"
şi “sffcaam"
.
Fiecare strateg concurent alege o configuraţie, iar câştigătorii sunt cei care aleg configuraţii echivalente cu cea a Strategului Şef.
Cerința
Date fiind configuraţia Strategului Şef, M
perechi de trupe care comută, şi cele N
configuraţii ale concurenţilor, numerotate de la 1
la N
, să se afişeze indecşii configuraţiilor câştigătoare.
Date de intrare
Fişierul armata_regelui.in
va conţine pe prima linie configuraţia Strategului Şef, pe a doua linie M
şi N
, pe următoarele M
linii perechile de trupe care comută, separate printr-un spaţiu, iar pe următoarele N
linii cele N
configuraţii concurente, fiecare pe câte o linie.
Date de ieșire
Fişierul armata_regelui.out
va conţine, în ordine crescătoare, indecşii configuraţiilor câştigătoare, fiecare pe câte o linie.
Restricții și precizări
M < 7
N < 5001
- Lungimea unei configuraţii
< 5001
- Fiecare test conţine
< 151
configuraţii câştigătoare - Toate testele conţin arcaşi. Cel putin
2
teste au< 20
arcaşi. Arcaşii sunt mereu reprezentaţi de litera'a'
şi sunt în general mai puţini decât celelalte trupe. Dacă \(t_1\) comută cu \(t_2\) atunci şi \(t_2\) comută cu \(t_1\).
Exemplu
armata_regelui.in
ffscaam 6 6 f s c m b g d z x y l t ffsacam ffscaam fsfcaam sffcaam scmaafssf ffztacm
armata_regelui.out
2 3 4
Cum e corect?
cout < "As la info";
cout << "As la info";
cout >> "As la info";
Felicitări! Poți mai mult?
Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.
Greșit, dar nu-i bai!
Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.
Rezolvare
Iată rezolvarea de 100 de puncte pentru problema Armata Regelui:
// autor: Iulia Tamas
#include <fstream>
#include <string.h>
#include <assert.h>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define A_SIZE 26 // alfabet
#define t_interval pair<pair<char, int>, pair<char, int> >
#define t_intervals vector<t_interval>
#define t_intervals_it vector<t_interval>::iterator
char comuta_cu[A_SIZE];
int ss_count[A_SIZE]; // numarul de litere de fiecare fel din ss_config
set<char> ss_in; // literele (trupele) din ss_config
set<int> ss_arc; // pozitiile arcasilor in ss_config
t_intervals ss_ivls;
int count[A_SIZE]; // numarul de litere din config curenta
void next_interval(string config, int clen, int *start, t_intervals &ivls) {
if (*start >= clen)
return;
// calculam descrirea intervalui format doar din literele lit si c_lit
char lit = config[*start];
char c_lit = comuta_cu[lit - 'a'];
int i, n_lit, n_c_lit;
n_lit = 0; // numar de aparitii litera
n_c_lit = 0; // numar de aparitii litera care comuta
for(i = *start; i < clen; i++) {
if(config[i] == lit) {
n_lit++;
continue;
}
if(config[i] == c_lit) {
n_c_lit++;
continue;
}
break;
}
ivls.push_back(make_pair(make_pair(lit, n_lit), make_pair(c_lit, n_c_lit)));
*start = i;
}
bool equal_intervals(t_interval a, t_interval b) {
return (a.first == b.first && a.second == b.second) ||
(a.first == b.second && a.second == b.first);
}
// Prespune: config de lungime corecta
bool same_arc(const string &config) {
set<int>::iterator it;
for(it = ss_arc.begin(); it != ss_arc.end(); it++){
if(config[*it] != 'a')
return false;
}
return true;
}
bool same_troups(const string &config) {
memset(count, 0, A_SIZE * sizeof(int));
string::const_iterator sit;
for (sit = config.begin(); sit != config.end(); sit++) {
if (++count[*sit - 'a'] > ss_count[*sit - 'a'])
return false;
}
return true;
}
int main() {
fstream fin, fout;
fin.open("armata_regelui.in", fstream::in);
fout.open("armata_regelui.out", fstream::out);
// ss_config
string ss_config;
fin >> ss_config;
int ss_len = ss_config.size();
// precalculari litere in ss_config
char lit;
string::iterator sit;
memset(comuta_cu, 0, A_SIZE);
memset(ss_count, 0, A_SIZE * sizeof(int));
ss_in.clear();
ss_arc.clear();
for (sit = ss_config.begin(); sit != ss_config.end(); sit++) {
lit = *sit;
assert(lit >= 'a' && lit <= 'z');
ss_count[lit - 'a']++;
ss_in.insert(lit);
if (lit == 'a') ss_arc.insert(sit - ss_config.begin());
}
// perechi care comuta
int M, N;
char t1, t2;
fin >> M >> N;
for(int i = 0; i < M; i++) {
fin >> t1 >> t2;
comuta_cu[t1 - 'a'] = t2;
comuta_cu[t2 - 'a'] = t1;
}
// precalculari intervale in ss_config
int start = 0;
do {
next_interval(ss_config, ss_len, &start, ss_ivls);
} while(start < ss_len);
// verificam fiecare configuratie
string config;
t_intervals ivls;
t_intervals_it iit;
for(int i = 1; i <= N; i++){
fin >> config;
int c_len = config.size();
if (c_len != ss_len){
continue;
}
// verificam pozitiile arcasilor
if (!same_arc(config)){
continue;
}
// verificam numar din fiecare trupa
if (!same_troups(config)){
continue;
}
// verificam fiecare interval in parte
ivls.clear();
start = 0;
iit = ss_ivls.begin();
do {
next_interval(config, c_len, &start, ivls);
if(!equal_intervals(ivls.back(), *iit)) {
break;
}
iit++;
} while(start < c_len && iit != ss_ivls.end());
if(start == c_len && iit == ss_ivls.end()) {
// acelasi numar de intervale si intervalele sunt identice
fout << i << "\n";
}
}
fin.close();
fout.close();
return 0;
}
Atenție
Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa .
Rezolvarea problemei #1830 Armata Regelui
Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #1830 Armata Regelui de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.
Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!