题目链接:点击打开链接
题意:给定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; } }
时间: 2024-10-11 07:21:19