Pagini recente » Politic2 | Cod sursa (job #2437095) | Cod sursa (job #1115432) | Monitorul de evaluare | Cod sursa (job #2962719)
// adn - https://infoarena.ro/job_detail/2962657?action=view-source
/*Nodurile:
X : C A A A A B C D E
Y : D E A C C C
Muchiile:
X -> Y : 2 (sf lui X cu în lui Y)
Y -> X : 1 (sf lui Y cu în lui X)
Caut o parcurgere a grafului astfel încât suma muchiilor sa fie maxima și fiecare nod parcurs o singura data
dp[i][conf] = suma maxima a muchiilor pana în i având vizitate nodurile din conf
dp[i][conf] = 0 (inițial)
Conf_nou += 1 << vec
dp[vec][conf_nou] = max(dp[vec][conf_nou], dp[i][conf] + muchie(i, vec))
For pt conf (de la 0 la 2^n -1)
For pt I (de la 0, la n - 1)
verify dacă i în conf
for(auto vec: ad[I])
verify faca vec nu e in conf
recurenta
*/
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>
#include <algorithm>
using namespace std;
ifstream fin("adn.in");
ofstream fout("adn.out");
int n;
string adn[20];
int cost[20][20];
int dp[20][1 << 20];
vector<string> new_adn;
bool eliminated[20];
pair<int, int> father[20][1 << 20];
vector<int> path;
int p[30005];
// ------------------------------ Word Distance ---------------------------------
int wordDistance(int word1, int word2) {
// Calculez subsecventa comuna intre sfarsitul primului cuvant si inceputul celui de-al doilea cuavnt
string str1 = adn[word1];
string str2 = adn[word2];
int w_size1 = str1.size();
int w_size2 = str2.size();
for (int i = 0; i < w_size1; i++) {
// Verific suprapunerea de la pozitia i in dreapta
bool same = true;
for (int j = i; (j < w_size1) && (j - i < w_size2); j++) {
// Verific daca cele doua cuvinte sunt identice
if (str1[j] != str2[j - i]) {
same = false;
break;
}
}
if (same) {
// Verific daca al doilea cuvant se gaseste in interiorul primului
if (w_size1 - i >= w_size2) {
return -1;
}
// Lungimea comuna a celor doua cuvinte
return w_size1 - i;
}
}
// Cuvintele nu au litere in comun
return 0;
}
// ------------------------------ Remake ADN ---------------------------------
void remakeADN() {
new_adn.push_back("");
// Daca sunt mai multe cuvinte identice, lasa doar prima aparitie
for(int i = 1; i < n; i ++)
for(int j = i + 1; j <= n; j ++) {
if(adn[i] == adn[j])
eliminated[j] = true;
}
for(int i = 1; i < n ; i ++)
for(int j = i + 1; j <= n; j ++) {
if(adn[i] == adn[j])
continue;
if(wordDistance(i, j) == -1) {
eliminated[j] = true;
//cout << i << " " << j <<'\n';
} else
if(wordDistance(j, i) == -1) {
eliminated[i] = true;
//cout << j << " " << i << '\n';
}
}
for(int i = 1; i <= n; i ++)
if(!eliminated[i]) {
new_adn.push_back(adn[i]);
}
}
// ------------------------------ Main ---------------------------------
int main() {
// Citesc string-urile de adn
fin >> n;
for(int i = 1; i <= n; i ++)
fin >> adn[i];
// Refac vectorul de string-uri astfel incat sa elimin string-urile ce se regasesc in interiorul altora
remakeADN();
n = new_adn.size() - 1;
// Suprascriu adn cu new_adn
for(int i = 1; i <= n ; i ++)
adn[i] = new_adn[i];
// Calculez costul distantelor dintre cuvinte
for(int i = 0; i <= n; i ++)
for(int j = 0; j <= n; j ++)
cost[i][j] = -1;
for(int i = 1; i < n; i ++)
for(int j = i + 1; j <= n; j ++) {
cost[i][j] = wordDistance(i, j);
cost[j][i] = wordDistance(j, i);
}
// Caut o parcurgere a grafului astfel încât suma muchiilor sa fie maxima și fiecare nod parcurs o singura data
// dp[i][conf] = suma maxima a muchiilor pana în i având vizitate nodurile din conf
for(int conf = 0; conf <= (1 << n) - 1; conf ++)
for(int i = 0; i < n; i ++)
if(conf & (1 << i)) // Verific daca i este deja vizitat
for(int j = 0; j < n; j ++)
if(cost[i + 1][j + 1] != -1 && !(conf & (1 << j))) { // Verific daca j este vecini si daca nu este vizitat
int new_conf = conf + (1 << j);
if(dp[j][new_conf] < dp[i][conf] + cost[i + 1][j + 1])
father[j][new_conf] = make_pair(i, conf);
dp[j][new_conf] = max(dp[j][new_conf], dp[i][conf] + cost[i + 1][j + 1]);
}
int last_node = -1;
int max_size = -1;
for(int i = 0; i <= n; i ++)
if(dp[i][(1 << n) - 1] > max_size) {
max_size = dp[i][(1 << n) - 1];
last_node = i;
}
int node = last_node;
int conf = (1 << n) - 1;
while(conf != 0) {
path.push_back(node + 1);
int new_conf = father[node][conf].second;
node = father[node][conf].first;
conf = new_conf;
}
reverse(path.begin(), path.end());
// Reconstituire sir
string result = "";
result += adn[path[0]];
for(int i = 1; i < path.size(); i ++) {
for(int j = cost[path[i - 1]][path[i]]; j <= adn[path[i]].size() - 1; j ++) {
result += adn[path[i]][j];
}
}
fout << result;
return 0;
}