WUTOJ 1284: Gold Medal(Java)
1284: Gold Medal
题目
  有N个砝码,重量为:3i-1(1<=i<=N),有一块重量为 W 的金牌。现在将金牌放在天平的左边。你需要将砝码放在左边或右边使得天平平衡,如果不能平衡输出"No way!",N个砝码不需要全部用完。更多内容点击标题。
参考
分析
  说实话,我也没想到这种做法,看的参考博客才明白的。(感觉他有部分代码处理的不是很好,可能是语言不同的关系吧。)
  没见过这类题的话,说实话不容易一下子想到居然和进制居然有一点点关系。
  不得不说砝码的重量很灵性。我们可以尝试在这里入手。首先将金牌的重量 W 转成三进制的,由于长度较大所以直接用数组保存比较好(我用的byte[])。下面举个例子:
输入:
4 16
输出:
LEFT:3 9
RIGHT:1 27
步骤:
通俗讲:
将金牌分成9,6,1三部分(提醒:金牌是固定放在左边的。16的三进制为121),然后发现砝码中有1,
于是就把1放在右边和左边的1平衡,然后继续,发现没有重量为6的砝码,但是你发现有重量为3和9的砝码,
于是就把3放左边,9放在右边,这样就与左边的6平衡了。继续,左边还有9,可是你还剩一个砝码(27),
根本不能平衡。于是你尝试将上一步中的9放在左边,此时左边有3,9和金牌的16一共是28,右边只有1,
但是还剩一个砝码(27),放在右边刚刚好。
代码流程:
16转成三进制为:121  // 左边高位,右边低位
第0位是'1',所以3^0=1放在右边
第1位是'2',权重是3^1=3,所以2*3=6,因为6不是3的幂,可是6=9-3,9和3都是3的幂,于是将3放
在左边,然后将121变成221
第2位是'2',权重是3^2=9,所以2*9=18,因为18不是3的幂,可是18=27-9,27和9都是3的幂,于是
将9放在左边,然后将221变成1221
第4位是'1',权重是3^3=27,所以1*27=27,是3的幂,于是将27放在右边。
代码
/**
 * time 741ms
 * @author PengHao
 * @version A1.0
 * @date 2019-04-29 下午5:39:25
 * Environment:	Windows 10
 * IDE Version:	Eclipse 2019-3
 * JDK Version:	JDK1.8.0_112
 */
import java.io.BufferedInputStream;
import java.util.Scanner;
public class Main {
	/**
	 * @Field <code>wTernary</code> W的三进制字节数组,下标从0开始
	 */
	private byte[] wTernary;
	/**
	 * @Field <code>leftArr</code> 左边的砝码情况
	 */
	private byte[] leftArr;
	/**
	 * @Field <code>rightArr</code> 右边的砝码情况
	 */
	private byte[] rightArr;
	/**
	 * @Field <code>tab</code> 3的n次幂(0<=n<=29),下标从0开始
	 */
	private long[] tab;
	/**
	 * @Field <code>ARR_LENGTH</code> 数组长度30
	 */
	private int ARR_LENGTH = 30;
	public Main() {
		Scanner sc = new Scanner(new BufferedInputStream(System.in));
		initTab(); // 初始化
		int N, W;
		while (sc.hasNext()) {
			N = sc.nextInt();
			W = sc.nextInt();
			wTernary = toTernary(W); // 转换成三进制
			weighing(wTernary); // 称重
			if (numOfWeights() <= N) {
				output(); // 输出
			} else {
				System.out.println("No way!");
			}
			System.out.println(); // 每组数据末尾空一行
		}
		sc.close();
	}
	/**
	 * Initialize <code>tab[]</code>
	 *
	 * @see #tab
	 */
	private void initTab() {
		tab = new long[ARR_LENGTH];
		tab[0] = 1;
		for (int i = 1; i < ARR_LENGTH; i++) {
			tab[i] = tab[i - 1] * 3;
		}
	}
	/**
	 * Converts an integer to a ternary byte array
	 *
	 * @param x 整数
	 * @return x的三进制字节数组
	 */
	private byte[] toTernary(int x) {
		byte[] y = new byte[ARR_LENGTH];
		for (byte i = 0; i < ARR_LENGTH && x > 0; i++) {
			y[i] = (byte) (x % 3);
			x /= 3;
		}
		return y;
	}
	/**
	 * @param x 需要称的重量
	 * @see #leftArr
	 * @see #rightArr
	 */
	private void weighing(byte[] x) {
		leftArr = new byte[ARR_LENGTH]; // 保存左边砝码
		rightArr = new byte[ARR_LENGTH]; // 保存右边砝码
		for (int i = 0; i < ARR_LENGTH; i++) {
			switch (x[i]) {
			case 1:
				rightArr[i] = 1; // 砝码3^i放到右边
				break;
			case 2:
				leftArr[i] = 1; // 砝码3^i放到左边
				x[i + 1]++; /// 要研究一下自增和赋值谁快
				break;
			case 3:
				x[i + 1]++;
				break;
			default:
			}
		}
	}
	/**
	 * @return 砝码个数
	 */
	private int numOfWeights() {
		int num; // 砝码个数
		for (num = ARR_LENGTH - 1; num >= 0; num--) {
			if (0 != leftArr[num] || 0 != rightArr[num]) {
				num++;
				break;
			}
		}
		return num;
	}
	/**
	 * Output
	 */
	private void output() {
		outputArr("LEFT:", leftArr);
		outputArr("RIGHT:", rightArr);
	}
	/**
	 * @param LR  左右?
	 * @param arr 需要输出的砝码
	 */
	private void outputArr(String LR, byte[] arr) {
		boolean first = true; // 是不是第一个砝码
		System.out.print(LR);
		for (int i = 0; i < ARR_LENGTH; i++) {
			if (1 == arr[i]) {
				if (first) {
					first = false;
				} else {
					System.out.print(" "); // 不是这一边的第一个砝码,要输出空格
				}
				System.out.print(tab[i]); // 输出砝码重量
			}
		}
		System.out.println();
	}
	public static void main(String[] args) {
		new Main();
	}
}
写在最后:
- 如需转载,请于首页至少注明链接形式的wowpH的博客这几个字;
- 代码原创,如需公开引用,不能删除首行注释(作者,版本号,时间等信息)。
- 如果有疑问欢迎评论留言,尽量解答。
WUTOJ 1284: Gold Medal(Java)的更多相关文章
- 如何夯实(Java)编程基础,并深入学习和提高
		如何夯实(Java)编程基础,并深入学习和提高? 240赞同反对,不会显示你的姓名 匿名用户 240 人赞同 多学习...网上自学的学习网站很多,见以下榜单~一.汇总榜单: 公开课_学习网站导航 收录 ... 
- TCL校园招聘——软件开发工程师(java) 只招5个。。。
		简介 TCL集团股份有限公司创立于1981年,是全球性规模经营的消费类电子企业集团之一,广州2010年亚运会合作伙伴,总部位于广东省惠州市仲恺高新区TCL科技大厦.旗下拥有TCL集团.TCL多媒体科技 ... 
- UEditor上传图片到七牛云储存(java)
		我们的网站一般放在虚拟空间或者服务器上,图片如果存在本地目录,会占用很多空间和流量,还增加了负担,好的办法是把图片存放到云储存服务里面,平时用url去拿 云储存:普遍说又拍云和七牛比较好,看到七牛免费 ... 
- 开源工作流 Bonita BPM  (JAVA)
		Bonita BPM 开源工作流 Bonita BPM (JAVA) http://www.bonitasoft.com/ 
- ZeroMQ(java)中对IO的封装(StreamEngine)
		哎,各种各样杂七杂八的事情...好久没有看代码了,其实要搞明白一个与IO相关的框架,最好的办法就是把它的I/0的读写两个过程搞清楚...例如在netty中,如果能将eventLoop的运行原理搞清楚, ... 
- 编译哈工大语言技术平台云LTP(C++)源码及LTP4J(Java)源码
		转自:编译哈工大语言技术平台云LTP(C++)源码及LTP4J(Java)源码 JDK:java version “1.8.0_31”Java(TM) SE Runtime Environment ( ... 
- 随机产生30个两个两位数相加的题目(java)
		编程思路: 1首先遇到JAVA产生随机数的问题. 2把产生的随机数设定范围. 3把划分的范围再分四个小区段分别对应四则运算法则加减乘除. 4打印输出. 题目源代码(Java) package coun ... 
- Android(java)学习笔记267:Android线程池形态
		1. 线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ... 
- MongoDB的update有关问题(JAVA)——如何一次更新所有的相同记录
		MongoDB的update问题(JAVA)——怎么一次更新所有的相同记录用如下这个函数:public WriteResult update(DBObject q, DBObject o, boo ... 
随机推荐
- EXTJS框架-入门实例
			extjs框架是一个JavaScript框架,可以渲染出丰富的控件 实例: 代码: <html> <head> <title>test</title> ... 
- RethinkDB是什么?—— 面向文档的NOSQL数据库,MVCC+Btree索引,pushes JSON to your apps in realtime采用push思路,优化的ssd存储
			RethinkDB是什么? RethinkDB是新一代的面向文档的数据库存储管理系统,原本是MySQL中针对SSD优化的一个存储引擎,后来脱离了MySQL成为了独立的系统. 数据如何存储在磁盘上? 数 ... 
- Linux信号使用及自定义信号
			linux自定义信号:https://www.cnblogs.com/bigben0123/p/3186661.html linux信号.值及解释:https://blog.csdn.net/luot ... 
- Redis 单线程却能支撑高并发 - 简书 https://www.jianshu.com/p/2d293482f272
			小结: 1.在 I/O 多路复用模型中,最重要的函数调用就是 select,该方法的能够同时监控多个文件描述符的可读可写情况:2.Redis 服务采用 Reactor 的方式来实现文件事件处理器(每一 ... 
- patch工具的使用
			1. 最简用法 patch -p1 < jello.patch 
- <javaScript>通过getElementsByTagName获取标签的class值
			console.log(p[1].id); console.log(p.item(1).id); console.log(p[2].getAttribute("class")); ... 
- List的remove()方法的三种正确打开方式
			转: java编程:List的remove()方法的三种正确打开方式! 2018年08月12日 16:26:13 Aries9986 阅读数 2728更多 分类专栏: leetcode刷题 版权声 ... 
- 34 Flutter仿京东商城项目 用户注册 注册流程 POST发送验证码  倒计时功能  验证验证码
			加群452892873 下载对应34课文件,运行方法,建好项目,直接替换lib目录 以下列出的是本课涉及的文件. RegisterFirst.dart import 'package:flutter/ ... 
- 丢失libiconv-2.dll解决办法以及无法定位输入点libiconv-2.dll到动态链接库
			摘自https://blog.csdn.net/mengxiangjia_linxi/article/details/78147348 丢失libiconv-2.dll解决办法以及无法定位输入点lib ... 
- REUSE_ALV_POPUP_TO_SELECT使用技巧
			可以实现弹出一个对话框,提供选择数据的功能…… 栗子1: CALL FUNCTION 'REUSE_ALV_POPUP_TO_SELECT' TYPE-POOLS slis. DATA: selec ... 
