这道题不是单纯的计算,而是一个根据目标函数,求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);
}
}