题目说每个相同文件(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("\n");
}//while
return 0;
}