微软2016年4月实习生笔试第一题-font size题解

这道题不是单纯的计算,而是一个根据目标函数,求s的最大值问题。运算逻辑是给s赋最大初值,然后不断s--,以达到目标函数。题目转换为屏幕字体匹配问题。
需要注意:
1、如何确定s字体大小的最大值(初值),因为字体是方的,而一页至少要有一个字母,所以,字体最大值是(W,H)min 有说初值选取可以进一步优化,选(W,H,P*H/S)min,这点没看。
2、确定目标函数,现在是给定了P,且带有s的函数计算值不能超过它,根据题意可得 (a[i]/(W/S))求和i=0~N-1每一段行数,求和为总行数,因为每一页行数是满的,但每一行字不一定是满的,总行数要<=P*H/S,因为s越大页数越大,所以要控制在p页内才行,s从max开始减小,满足条件,即跳出循环。
3、注意一点a[i]/(W/S)的时候,不能直接用int计算,因为存在除不尽的情况,这个时候需要判断a[i]%(W/S)是否为0,不为0表示有非满字行,所以要+1,即:
a[i]%(W/S)==0?0:1;否则计算总行数会错误,丢失精度

import java.util.Scanner;

//微软笔试第一题 font size,AC,用最大化函数做,s字母是个方的,屏幕匹配问题,word等文本处理
public class Main {

	/**
	 * @param args
	 */
	Main(Scanner in){
		int TASK = in.nextInt();
		String delet = in.nextLine();//废弃的一次流
			for(int i=0;i<TASK;i++){//输出循环,几个testcase
				String args = in.nextLine();
				int[] iargs = argsCase(args);
				int[] a = new int[iargs[0]];
				for(int j=0;j<iargs[0];j++){
					a[j] = in.nextInt();
				}
				String delet2 = in.nextLine();
				int output = maxfontSize(iargs[0], iargs[1], iargs[2], iargs[3], a);
				System.out.println(output);
			}
			
		//可以不用再重新遍历,运算的时候一起输出结果
		in.close();
		
	}
	//用来储存一个testcase的参数
	public int[] argsCase(String args){
		String[] fargs = args.split(" ");
		int[] args2 = new int[4];
		for(int i=0;i<4;i++){
			args2[i] = Integer.parseInt(fargs[i]);
		}
		return args2;
	}
	public int maxfontSize(int N,int P,int W,int H,int a[]){
		int Smax = W>H?H:W;//s要赋初值的
		boolean b = true;
		if(1<=N && N<=1000 && 1<=W && W<=1000 && 1<=H && H<=1000 && 1<=P && P<=1000000 ){
			 while(b){//这个循环是减小Smax来达到目标函数,每循环一次,即计算一次
				 int character = W/Smax;
				 int lines = H/Smax;
				 int A = 0;
				 for(int i=0;i<a.length;i++){
					 A+=(a[i]/character)+(a[i]%character==0?0:1);//总行数累加计算,A作为累加载体,后面的求余是因为存在一行不满字情况,上取整
				 }
				 if(A<=P*lines){//循环边界,while do是先判断,在执行,所以存在临界点满足while但do后就不满足情况,do while相反
					 b = false;
					 return Smax;
				 }else{
					 Smax--;
				 }
			 }
		}
		return 0;
	}
	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		Scanner in = new Scanner(System.in);
		Main  fonts = new Main(in);

	}

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值