题目说每个相同文件(01串)都被撕裂成两部分,要求拼凑成原来的样子,如果有多种可能输出一种。
我标题写着排列组合,其实不是什么高深的数学题,只要把最长的那几个和最短的那几个凑一起,然后去用其他几个验证就行了,反正我的验证是非常暴力的,看起来。。。(其实加了个二维数组判定不是很吃复杂度)
代码:
#include <string> #include <cstring> #include <stdio.h> #include <algorithm> #include <iostream> using namespace std; const int maxn = 150; string p[maxn]; int n, cnt, min, max; bool flag, used[maxn]; bool cmp (string a, string b) { return a.size() < b.size(); } bool check(string str) { for (int i = 0; i < cnt; i++) for (int j = 0; j < cnt; j++) { if (!used[i] && !used[j] && p[i] + p[j] == str) used[i] = used[j] = true; }//for for (int i = 0; i < cnt; i++) if (used[i] == false) return false; return true; } int main() { cin >> n; getline(cin, p[0]); getline(cin, p[0]); while(n--) { cnt = 0; while (getline(cin, p[cnt]) && !p[cnt].empty()) cnt++; sort(p, p + cnt, cmp); flag = false; for (int i = 0; !flag && p[i].size() == p[0].size(); i++) for (int j = cnt - 1; !flag && p[j].size() == p[cnt - 1].size(); j--) { memset(used, 0, sizeof(used)); used[i] = used[j] = 1; if (check(p[i] + p[j])) { cout << p[i] + p[j] << endl; flag = true; break; }//if memset(used, 0, sizeof(used)); used[i] = used[j] = 1; if (check(p[j] + p[i])) { cout << p[j] + p[i] << endl; flag = true; break; }//if }//for if (n) printf(" "); }//while return 0; }