第一道想了一天想出来的的题目。
思路:
既然是找最短的,那BFS可以考虑。
可以肯定的是,最小的结果的最大值一定是输入的最大值。
考虑这样一组数据
4
3 5 17 19
结果是
4
0 2 5 19
可以猜到,最后结果的每个数都只能从原数据中或者各个原数据相减得到的新数据中选出。
那就把原数据扩大,然后BFS选即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1.0);
int n, m, k;
vi r, p;
queue<vi> q;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
int times = 1;
while(cin >> n, n){
r.clear();
for(int i = 0; i < n; i++){
int v;
cin >> v;
r.push_back(v);
}
sort(r.begin(), r.end());
for(int i = 1; i < (int)r.size(); i++)
if(r[i] == r[i - 1]){
r.erase(r.begin() + i);
i--;
}
set<int> rec;
for(int i = 0; i < (int)r.size(); i++)
for(int j = i + 1; j < (int)r.size(); j++)
rec.insert(r[j] - r[i]);
for(int i = 0; i < (int)r.size() - 1; i++)
rec.insert(r[i]);
p.clear();
for(auto it = rec.begin(); it != rec.end(); ++it)
p.push_back(*it);
while(!q.empty())
q.pop();
q.push(vi(1));
while(!q.empty()){
vi cur = q.front();
q.pop();
map<int, int> mp;
for(int i = 0; i < (int)cur.size(); i++){
mp[cur[i]] |= 1;
mp[r.back() - cur[i]] |= 1;
}
for(int i = 0; i < (int)cur.size(); i++)
for(int j = i + 1; j < (int)cur.size(); j++)
mp[cur[j] - cur[i]] |= 1;
bool fin = true;
for(int i = 0; i < (int)r.size() - 1; i++)
if(!mp[r[i]]){
fin = false;
break;
}
if(fin){
cout << "Case " << times++ << ":" << endl;
cout << (1 + cur.size()) << endl;
for(int i = 0; i < (int)cur.size(); i++)
cout << cur[i] << " ";
cout << r.back() << endl;
break;
}
for(int pos = upper_bound(p.begin(), p.end(), cur.back()) - p.begin(); pos < (int)p.size(); pos++){
cur.push_back(p[pos]);
q.push(cur);
cur.pop_back();
}
}
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。