首页 > 代码库 > UvaLive 3403 Mobile Computing 枚举二叉树

UvaLive 3403 Mobile Computing 枚举二叉树

题目链接:点击打开链接

题意:

给定房间宽度r和s个石头重量

设计一个尽量宽但宽度不超过房间宽度r的天平,使得能把所有石头放在天平上

(天平的一端要么挂一个石头,要么挂一个天平)

天平的平衡满足杠杆原理(两端重量的比值与两端距离悬挂天平点的距离成反比,每根天平杆长度为1)

输出最大的宽度(若不能把石头都挂上输出-1)

思路:

枚举计算每一个状态时的最大宽度。

若这个状态只有一个石头,那么得到的天平就认为是(0,0) (0,0)的意思是以天平支点为准,向左延展的长度和向右延展的长度

否则一定是由2个子状态合成,即2个子天平拼出来。

枚举其中一个子天平的状态,另一个子天平的状态异或一下就得到了,

则向左延展的长度为 max(父天平向左延展的长度+左子天平向左延展的长度,右子天平向左延展的长度-父天平向左延展的长度)

向右延展长度同理。


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 {
	class Node{
		double l, r;
		Node(double l, double r){
			this.l = l;
			this.r = r;
		}
	}
	static int N = 65;
	double R; int s;
	double[] a = new double[10], w = new double[N];
	ArrayList<Node>[] E = new ArrayList[N];
	void work() {
		for(int i = 0; i < N; i++)	E[i] = new ArrayList();
		int T = cin.nextInt();
		while(T-->0){
			R = cin.nextDouble();
			s = cin.nextInt();
			for(int i = 0; i < s; i++)a[i] = cin.nextDouble();
			for(int i = 0; i < (1<<s); i++){
				w[i] = 0;
				for(int j = 0; j < s; j++)
					if(((1<<j)&i)>0)
						w[i] += a[j];
			}
			for(int i = 0; i < N; i++) E[i].clear();
			 for(int st = 1; st < (1<<s); st++){
		            if(0 == ((st-1)&st)) {//若这个状态里只有一个石头
		                E[st].add(new Node(0,0));
		                continue;
		            }
		            for(int sb=(st-1)&st;sb > 0;sb=(sb-1)&st){
		                int sa=st^sb;
		                double rs=w[sb]/w[st],ls=w[sa]/w[st];
		                for(int i = 0; i < E[sb].size(); i++)
		                	for(int j = 0; j < E[sa].size(); j++)
		                	{
		                    double l=max(E[sb].get(i).l+ls,E[sa].get(j).l-rs);
		                    double r=max(E[sb].get(i).r-ls,E[sa].get(j).r+rs);
		                    if(r+l>R) continue;
		                    E[st].add(new Node(l,r));
		                }
		            }
		        }
			 double ans = -1;
			 for(int i = 0; i < E[(1<<s)-1].size(); i++)
				 ans=max(ans,E[(1<<s)-1].get(i).l+E[(1<<s)-1].get(i).r);
			 out.println(ans);			 
		}
	}
	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 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;
	}
}


UvaLive 3403 Mobile Computing 枚举二叉树