UVA 1377 Ruler bfs+状压搜索

题目链接:点击打开链接

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

UVA 1377 Ruler bfs+状压搜索的相关文章

HDU 5025 (BFS+记忆化状压搜索)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5025 题目大意: 迷宫中孙悟空救唐僧,可以走回头路.必须收集完钥匙,且必须按顺序收集.迷宫中还有蛇,杀蛇多耗时1,蛇杀完就没了.问最少耗时. 解题思路: 2014广州网赛的水题之一.当时没刷过BFS状压,结果悲剧了. 首先这题可以压钥匙,也可以压蛇,不过压钥匙内存岌岌可危,于是就压蛇吧. 设f[x][y][key][snake]为在(x,y)点,已经取得的钥匙key,以及杀蛇snake的状态. 对

【HDU 4771 Stealing Harry Potter&#39;s Precious】BFS+状压

2013杭州区域赛现场赛二水... 类似“胜利大逃亡”的搜索问题,有若干个宝藏分布在不同位置,问从起点遍历过所有k个宝藏的最短时间. 思路就是,从起点出发,搜索到最近的一个宝藏,然后以这个位置为起点,搜索下一个最近的宝藏,直至找到全部k个宝藏.有点贪心的感觉. 由于求最短时间,BFS更快捷,但耗内存,这道题就卡在这里了... 这里记录了我几次剪枝的历史...题目要求内存上限32768KB,就差最后600KB了...但我从理论上觉得已经不能再剪了,留下的结点都是盲目式搜索必然要访问的结点. 在此贴

hdu 2209 bfs+状压

http://acm.hdu.edu.cn/showproblem.php?pid=2209 不知为啥有种直觉,会出状压+搜索的题,刷几道先 简单的BFS,状压表示牌的状态, //#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <cstring> #include <algorithm> #include <string> #

hdu 5094 Maze (BFS+状压)

题意: n*m的迷宫.多多要从(1,1)到达(n,m).每移动一步消耗1秒.有P种钥匙. 有K个门或墙.给出K个信息:x1,y1,x2,y2,gi    含义是(x1,y1)与(x2,y2)之间有gi.gi=0:墙   1,2,3.... :第1种门,第2种门,第3种门..... 有S把钥匙.给出S个信息:x1,y1,qi    含义是位置(x1,y1)上有一把第qi种的钥匙. 问多多最少花多少秒到达(n,m).若无法到达输出-1. 数据范围: (1<= n, m <=50, 0<= p

hdu 4771 Stealing Harry Potter&#39;s Precious (BFS+状压)

题意: n*m的迷宫,有一些格能走(“.”),有一些格不能走(“#”).起始点为“@”. 有K个物体.(K<=4),每个物体都是放在“.”上. 问最少花多少步可以取完所有物体. 思路: BFS+状压,看代码. 代码: struct node{ int x,s; node(int _x,int _s){ x=_x, s=_s; } }; int n,m,k,sx,sy; char graph[105][105]; int px[5],py[5]; int dp[105][105][35]; int

UVA 11825 Hackers&#39; Crackdown 状压DP

感觉白书上的做法很神! 首先状压表示电脑之间的联通关系,然后预处理出所有关闭电脑的组合达到的状态,然后枚举每个状态并且枚举每个状态的所有子集,之后无脑递推就木有了. 关于枚举一个状态所有子集的小技巧:假设当前状态是S0 有 for s = s0; s != 0; s =  (s - 1) & s0 #include <cstdio> #include <cstring> #include <iostream> #include <map> #incl

HDU 4856 Tunnels(BFS+状压DP)

HDU 4856 Tunnels 题目链接 题意:给定一些管道,然后管道之间走是不用时间的,陆地上有障碍,陆地上走一步花费时间1,求遍历所有管道需要的最短时间,每个管道只能走一次 思路:先BFS预处理出两两管道的距离,然后状态压缩DP求解,dp[s][i]表示状态s,停在管道i时候的最小花费 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using

HDU-3502-Huson&#39;s Adventure Island(BFS+状压DP)

Problem Description A few days ago, Tom was tired of all the PC-games, so he went back to some old FC-games. "Hudson's Adventure Island" was his favorite which he had played thousands of times. But to his disappointed, the more he played, the mo

UVA 11691 - Allergy Test(状压dp+贪心)

题目链接:11691 - Allergy Test 题意:这题题意看了老半天都没弄懂,好在后面找到个PPT,上面有中文题意- -,不过上面的做法是纯贪心,挺巧妙的但是感觉有点不靠谱, 下载地址:http://par.cse.nsysu.edu.tw/~advprog/advprog2011/11691.ppt 給N種過敏原的存活期,每天可把一種過敏原注入人體內.若有兩個以上過敏原存活於人體中,則無法進行實驗(也就是每種過敏原都必須有一天是單獨存活於人體中).實驗結束於最後的過敏原死亡的那天,求最