题目链接:点击打开链接
题意:给定n个刻度。下面是n个刻度。
要构造一个尺子使得上面的n个刻度能直接量出来。
且要满足尺子上的刻度线个数最少,最少的情况下尺子最短。
第一个刻度总为0
题目保证总是存在<7个刻度线的解。
思路:
bfs,每次枚举新加一个刻度后,哪些可以直接量出来,用二进制表示,然后暴力搜
剪枝:
1、若加入一个新刻度后并不能多测量给定的n个刻度那么加入的刻度就无效(即加入前和加入后的状态相同)
2、尺子的长度若大于最大刻度则无效
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.Queue;
public class Main {
static int N = 55;
int n, max;
int[] a = new int[N];
int[] id = new int[1000005];
class Node{
TreeSet<Integer> G;
int state;
Node(){
state = 0;
G = new TreeSet();
}
public Node clone(){
Node hehe = new Node();
hehe.state = this.state;
Iterator<Integer> it = this.G.iterator();
while(it.hasNext())
hehe.G.add(it.next());
return hehe;
}
void put(){
System.out.print(state+":");
Iterator it = G.iterator();
while(it.hasNext())
System.out.print(it.next()+" ");System.out.println();
}
}
Node p;
TreeSet<Integer> ans = new TreeSet();
Queue<Node> Q = new LinkedList<Node>();
void BFS(){
Q.clear();
p = new Node();
p.G.add(0);
Q.add(p);
while(Q.size()>0)
{
p = Q.poll();
if(p.state == (1<<n)-1)
{
if(ans.size() < p.G.size())continue;
if(ans.size() == p.G.size() && ans.last()<=p.G.last())continue ;
Iterator<Integer> it = p.G.iterator();
ans.clear();
while(it.hasNext())
ans.add(it.next());
continue;
}
if(p.G.size() == 7)continue;
Iterator<Integer> it = p.G.iterator();
while(it.hasNext())
{
int num = it.next();
Node next;int i;
for(i=0; i<n; i++)
{
if((p.state&(1<<i))>0) continue; //刻度已选取
int v = num+a[i];
if(p.G.contains(v)) continue;//刻度已可表示
if(v>max) continue;//超过最大刻度,不需要
next=p.clone();
next.G.add(v);
Iterator<Integer> it2 = p.G.iterator();
while(it2.hasNext())
{
int x=abs(v-it2.next());
if(id[x]!=-1)
next.state|=(1<<id[x]);
}
if(next.state!=p.state)
Q.add(next.clone());
}
}
}
}
void init(){
ans.clear();
for(int i = 1; i <= n; i++) ans.add(cin.nextInt());
max = ans.last();
for(int i = 0; i <= max; i++)id[i] = -1;
Iterator<Integer> it = ans.iterator();
n = 0;
while(it.hasNext()){
a[n++] = it.next();
id[a[n-1]] = n-1;
}
}
void put(){
out.println(ans.size());
Iterator<Integer> it = ans.iterator();
while(it.hasNext()){
out.print(it.next()+" ");
}
out.println();
}
void work() {
int Cas = 1;
while(true){
n = cin.nextInt(); if(n == 0)break;
out.println("Case "+(Cas++)+":");
init();
BFS();
put();
}
}
Main() {
cin = new Scanner(System.in);
out = new PrintWriter(System.out);
}
public static void main(String[] args) {
Main e = new Main();
e.work();
out.close();
}
public Scanner cin;
public static PrintWriter out;
int upper_bound(int[] A, int l, int r, int val){//upper_bound(A+l,A+r,val)-A;
int pos = r;
r -- ;
while(l <= r){
int mid = (l+r)>>1;
if(A[mid]<=val){
l = mid+1;
}
else {
pos = mid;
r = mid-1;
}
}
return pos;
}
/*class Queue {
int[] queue = new int[N+10];
int front, rear;
// front <= rear
Queue() {
// queue = new int[x];
}
void clear() {
front = rear = 1;
}
boolean empty() {
return front == rear;
}
int size() {
return rear - front;
}
int front() {
return queue[front];
}
int rear() {
return queue[rear - 1];
}
void push_rear(int x) {
queue[rear++] = x;
}
void pop_front() {
front++;
}
void pop_rear() {
rear--;
}
}
/**/
int max(int x, int y) {
return x > y ? x : y;
}
int min(int x, int y) {
return x < y ? x : y;
}
double max(double x, double y) {
return x > y ? x : y;
}
double min(double x, double y) {
return x < y ? x : y;
}
static double eps = 1e-8;
int abs(int x) {
return x > 0 ? x : -x;
}
double abs(double x) {
return x > 0 ? x : -x;
}
boolean zero(double x) {
return abs(x) < eps;
}
}