阿里巴巴2018秋招在线编程测验:
* 题目:假设靶场有n个靶子,n个靶子的分数为数组score[n],score[i]为0的靶子不能射击。
* 射中第i个靶子的,假如第i个靶子的左右两边均有相邻靶子,则射中第i个靶的得分为score[left]*score[i]*score[right]
* ,并且射中之后,score[left]和score[right]变为相邻的两个靶子。
* 当射中的靶子右边没有相邻的靶子则得分为score[left]*score[i];左边同理。
* 若左右两边均没有靶子,则得分为score[i]
* 题目:假设靶场有n个靶子,n个靶子的分数为数组score[n],score[i]为0的靶子不能射击。
* 射中第i个靶子的,假如第i个靶子的左右两边均有相邻靶子,则射中第i个靶的得分为score[left]*score[i]*score[right]
* ,并且射中之后,score[left]和score[right]变为相邻的两个靶子。
* 当射中的靶子右边没有相邻的靶子则得分为score[left]*score[i];左边同理。
* 若左右两边均没有靶子,则得分为score[i]
* 求最多能得多少分?
/**
* @author yangs
*
*思路。
*1、每次查找最佳的打靶点,进行打靶,累加此次打靶所获得的分数,打靶之后把该靶分数标位-1
*2、查找最佳的打靶点策略:
* (1)首先查询中间所有可打靶(即未打过的靶score不为0的点)点(因为中间位置可以获得两次乘法,如果首先打去两端的靶子,那么将可能减少一次称的机会;计算得分不为0的位置),
* (2)再在所有候选打靶点选择score最小的打靶(选score最小的可以让大的score有相乘的机会多一些,从而总分数高)。
* (3) 若有打靶位置i,则进行打靶,并计算本次打靶所得分数,累加到总分,最后标记 score[i]=-1,跳转回执行第(1)步;否则进行到第(4)步。
* (4)如果在中间位置查询不到打靶位置,那么查找从两端可打靶位置。若也为找不到合法的打靶位置,说明打靶可以结束了,循坏break;否则返回执行第(3)步。
*3、示例:2 4 5 6 3 2;
* 第1次打靶:2 4 5 6 3 2 最佳打靶位3,得分36,
* 第2次打靶:2 4 5 6 2 最佳打靶位4,得分40,
* 第3次打靶:2 5 6 2 最佳打靶位5,得分60,
* 第4次打靶:2 6 2 最佳打靶位6,得分24,
* 第5次打靶:2 2 最佳打靶位2,得分4
* 第6次打靶:2 最佳打靶位2,得分2,
* 总分得:36+40+60+24+4+2=166)。
* 示例:2 4 5 0 3 2;
* 第1次打靶:2 4 5 0 3 2 最佳打靶位4,得分40,
* 第2次打靶:2 5 0 3 2 最佳打靶位2,得分10,(中间已经找不到打靶位置,打去两端的)
* 第3次打靶:5 0 3 2 最佳打靶位2,得分6,
* 第3次打靶: 5 0 3 找不到打靶位置,循坏结束。
* 总分得40+10+6=56。
*
*/
public class Main {
public int deal(int []score) {
int n=score.length;
int sum=0;
for(int j=0;j<n;j++)
{
int k=find(score,1,n-1);
if(k==-1&&(k=find(score,0,n))==-1)break;
int grade=score[k];//当前靶点得分
if(k>0){
int l=k-1;
while(l>=0&&score[l]==-1)l--;
if(l>=0){//如果左边存在没打过的靶
//如果左边的靶分数不为0
if(score[l]>0)grade*=score[l];
else continue;//左边的靶分数为结束本次当前循坏
}
}
if(k+1<n){
int l=k+1;
while(l<n&&score[l]==-1)l++;
if(l<n){//如果右边边存在没打过的靶
if(score[l]>0)grade*=score[l];
else continue;
}
}
sum+=grade;
score[k]=-1;
}
return sum;
}
/**
* 查找最佳打靶点
* @param score
* @param j 查找起始位置
* @param i 查找结束位置
* @return bestIndex 最佳打靶位置
*/
private int find(int[] score, int j,int i) {
int min=Integer.MAX_VALUE;
int bestIndex=-1;
for(;j<i;j++){
//如果当前点score为0或-1,则跳过该点
if(score[j]<=0)continue;
if(j>0){
int k=j-1;//找出左边相邻的靶
while(k>=0&&score[k]==-1)k--;
//如果左边相邻的靶为0,则当前靶点无效,打了也是0分,结束本次当前循坏
if(k>=0&&score[k]==0)continue;
}
if(j+1<i){
int k=j+1;//找出右边相邻的靶
while(k<i&&score[k]==-1)k++;
//如果右边相邻的靶为0,则当前靶点无效,打了也是0分,结束本次当前循坏
if(k<i&&score[k]==0)continue;
}
//候选靶点中取较小的靶点
if(min>score[j]){
min=score[j];
bestIndex=j;
}
}
return bestIndex;
}
}
求教大家,有没有好一点的算法