Xiaoming wants to make a special ruler, which can directly measure several given lengths. Xiaoming hopes to find a way, making the scale on ruler as few as possible, while for a given length, there exists two scales on ruler and the distance between the two scales is equal to the given length. For scales as few as possible, we also hope the length of ruler as short as possible to save the material cost.
The last case is followed by a line containing a zero.
Note: output scales in ascending order, the first number is always 0. You can assume that M won‘t exceed 7.
6 5 15 20 25 35 40 0
Case 1: 4 0 5 25 40
题意:给定一些要测量的刻度,然后你要制造一把尺子,能测量这些,要求尺子的刻度数尽量少,并且尺子尽量短,题目保证刻度数不会大于7.
思路:BFS + 状态判重。每个尺子要测量刻度肯定由当前有的刻度去加或减可以得到一个新刻度,然后新刻度可以和其他的得到一些可以测量的刻度,注意M不会大于7,也就是说虽然题目说测量50个刻度,实际上只有C72,21个刻度,有很多重复的,这使得搜索时间复杂度不会太高。不过题目还有个条件,就是做出来的尺子最大刻度不能超过要测量的最大刻度,这点题目没说,WA了,还是看了别人题解才知道。
代码:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> #include <queue> #include <set> using namespace std; const int MAXN = 1000005; int N, n, id[MAXN], d[25], cas = 0, Max, vis[2222222]; set<int>ans; struct S { int state; set<int>ans; } p; void init() { int D; n = 0; ans.clear(); memset(id, 0, sizeof(id)); memset(vis, 0, sizeof(vis)); for (int i = 0; i < N; i++) { scanf("%d", &D); if (!id[D]) { d[n++] = D; id[D] = 1; } } sort(d, d + n); Max = d[n - 1]; memset(id, -1, sizeof(id)); for (int j = 0; j < n; j++) id[d[j]] = j; } void BFS() { queue<S>Q; p.ans.clear(); p.ans.insert(0); p.state = 0; Q.push(p); while (!Q.empty()) { p = Q.front(); Q.pop(); if (p.state == (1<<n) - 1) { if (ans.size() == 0) { ans = p.ans; } else { if (ans.size() < p.ans.size()) return; else if (ans.size() > p.ans.size()) ans = p.ans; else { if (*ans.rbegin() > *p.ans.rbegin()) ans = p.ans; } } } if (p.ans.size() == 7) continue; for (int i = 0; i < n; i++) { if ((p.state&(1<<i))) continue; for (set<int>::iterator it = p.ans.begin(); it != p.ans.end(); it++) { if (*it > d[i]) { S q = p; int sum = *it - d[i]; for (set<int>::iterator it2 = q.ans.begin(); it2 != q.ans.end(); it2++) { int nu = abs(*it2 - sum); if (id[nu] == -1) continue; q.state = (q.state|(1<<id[nu])); } q.ans.insert(sum); if (!vis[q.state]) { Q.push(q); vis[q.state] = 1; } } if (*it + d[i] <= Max) { S q = p; int sum = *it + d[i]; for (set<int>::iterator it2 = q.ans.begin(); it2 != q.ans.end(); it2++) { int nu = abs(*it2 - sum); if (id[nu] == -1) continue; q.state = (q.state|(1<<id[nu])); } q.ans.insert(sum); if (!vis[q.state]) { Q.push(q); vis[q.state] = 1; } } } } } } void solve() { BFS(); int bo = 0; printf("Case %d:\n%d\n", ++cas, ans.size()); for (set<int>::iterator it = ans.begin(); it != ans.end(); it++) { if (bo++) printf(" "); printf("%d", *it); } printf("\n"); } int main() { while (~scanf("%d", &N) && N) { init(); solve(); } return 0; }
原文:http://blog.csdn.net/accelerator_/article/details/18312437