Pentru un număr natural nenul n
, să considerăm toate numerele naturale nenule mai mici sau egale cu n
, luând fiecare număr de câte două ori: 1, 1, 2, 2, 3, 3, ... , n, n
. Aceste numere le amestecăm aleator, şi le aranjăm pe două linii a câte n
elemente. Structura astfel obţinută o vom numi o bipermutare. În figurile 1, 2 şi 3 avem câte un exemplu de bipermutare pentru n=5
.
O bipermutare este perfectă, dacă ambele linii ale structurii reprezintă câte o permutare (vezi figurile 2 şi 3).
Prin mutare pe poziţia p
, înţelegem interschimbarea elementelor de pe aceeaşi coloană p
. În exemplele de mai jos, bipermutarea perfectă din figura 2 s-a obţinut din bipermutarea din figura 1, aplicând o mutare pe poziţa 2
. Bipermutarea perfectă din figura 3 s-a obţinut din bipermutarea din figura 1, aplicând mutări pe poziţiile 1
, 2
, 4
şi 5
.
Cerința
Cunoscând o bipermutare, determinaţi:
- numărul bipermutărilor perfecte distincte ce se pot obţine prin mutări;
- numărul minim de mutări prin care se poate obţine o bipermutare perfectă;
- o bipermutare perfectă obţinută din bipermutarea iniţială.
Date de intrare
Fișierul de intrare biperm.in
conține pe prima linie valoarea lui n
. Următoarele două linii conţin, fiecare, câte n
elemente separate prin câte un spaţiu, formând o bipermutare.
Date de ieșire
Fișierul de ieșire biperm.out
va conține:
- pe prima linie două numere naturale separate printr-un spaţiu, reprezentând numărul bipermutărilor perfecte distincte ce se pot obţine din bipermutarea dată, respectiv numărul minim de mutări prin care se poate obţine o bipermutare perfectă;
- pe următoarele două linii se vor tipări câte
n
numere separate prin spaţiu, reprezentând o bipermutare perfectă obţinută din bipermutarea dată.
Restricții și precizări
2 < n ≤ 10 000
;- calculul corect al numărului bipermutărilor perfecte distincte valorează
30%
din punctaj; - calculul corect al numărului minim de mutări valorează
10%
din punctaj; - tipărirea unei bipermutări perfecte valorează
60%
din punctaj. Pot exista mai multe soluţii, se va admite orice soluţie corectă; - se garantează că numărul bipermutărilor perfecte distincte nu depăşeşte
2 000 000 000
pentru niciun test. - pentru
40%
din testen ≤ 20
- pentru
40%
din teste20 < n ≤ 400
- pentru
20%
din teste400 < n ≤ 10 000
Exemplu
biperm.in
5 1 5 5 3 4 3 2 2 4 1
biperm.out
4 1 1 2 5 3 4 3 5 2 4 1
Explicație
Sunt 4
permutări perfecte. Numărul minim de mutări este 1
şi există două soluţii cu număr minim de mutări:
1 2 5 3 4 1 5 2 3 4 3 5 2 4 1 şi 3 2 5 4 1
Celelalte două soluţii, ce nu se obţin din număr minim de mutări sunt:
3 2 5 4 1 3 5 2 4 1 1 5 2 3 4 şi 1 2 5 3 4
Pentru a treia cerinţă oricare dintre cele 4
soluţii este acceptată.
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 Biperm:
// prof. Szabo Zoltan - Mures
// 100 puncte
#include <fstream>
#include <iostream>
using namespace std;
int viz[2][10003],a[2][10003],b[2][10003];
int main()
{ int n,i,j,p,nrmin,invers,l,poz,ant,aux,urmviz;
ifstream fin("biperm.in");
ofstream fout("biperm.out");
fin>>n;
for (i=0;i<2;++i) // matricea viz[x][i] are semnificatia:
for (j=1;j<=n;++j)
{
fin>>a[i][j]; // numarul i apare in bipermutare pe pozitiile
if (viz[0][a[i][j]]==0) // viz[0][i] si viz[1][i]
viz[0][a[i][j]]=j;
else
viz[1][a[i][j]]=j;
}
p=1; // p - numarul solutiilor distincte, produs, putere a lui 2
nrmin=0; // nrmin - va numara interschimbarile efectuate pentru cazul optim
for (i=1;i<=n;++i)
if (b[0][i]==0)
{ l=1; invers=0;poz=i; // reconstruim ciclurile: l lungimea ciclului
// invers= cate arce sunt in ciclu cu sensul invers
b[0][poz]=a[0][poz]; // poz = pozitia curenta in ciclu
b[1][poz]=a[1][poz]; // ant = pozitita anterioara in ciclu
ant=poz; // in b se construieste permutarea dubla ceruta
urmviz=b[1][poz]; // urmatorul nod spre vizitare in lant
if (viz[0][urmviz]==poz) //
poz=viz[1][urmviz];
else
poz=viz[0][urmviz]; // lant continua este muchia a[0][poz] si a[1][poz]
while (!b[0][poz])
{
if (a[0][poz]==b[1][ant])
{
b[0][poz]=a[0][poz];
b[1][poz]=a[1][poz];
l++;
ant=poz;
urmviz=b[1][poz];
if (viz[0][urmviz]==poz)
poz=viz[1][urmviz];
else
poz=viz[0][urmviz];
}
else
{
b[0][poz]=a[1][poz];
b[1][poz]=a[0][poz];
l++;invers++; // am gasit un nou arc invers
ant=poz; //
urmviz=b[1][poz];
if (viz[0][urmviz]==poz)
poz=viz[1][urmviz];
else
poz=viz[0][urmviz];
}
}
if (l>1)
p*=2;
if (invers>l-invers)
nrmin+=l-invers;
else
nrmin+=invers;
}
fout<<p<<" "<<nrmin<<"
";
for(i=0;i<2;++i)
{ for(j=1;j<n;++j)
fout<<b[i][j]<<" ";
fout<<b[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 #1041 Biperm
Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #1041 Biperm 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!