UVA 1377 Ruler bfs+状压搜索

20 篇文章 0 订阅

题目链接:点击打开链接

题意:给定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;
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值