2017年華爲Fx計劃在線機試題(詳解)

1,題目描述
小k是x區域的銷售經理,他平時常駐“5”城市,並且經常要到“1”,“2”,“3”,“4”,“6”城市出差。當機場出現大霧的情況下,會導致對應城市的所有航班的起飛及降落均停止(即不能從該城市出發,其他城市也不能到達該城市)。小k希望知道如果他需要到x城市出差時,如果遇到y城市出現大霧,他最短的飛行時間及飛行路徑。
注意:當兩個城市不可達時,消耗時間默認取1000.
各城市間的飛行時間如下表所示,行代表始發城市,列代表終點城市,矩陣中的值代表從始發城市飛行到終點城市所消耗的時間(單位小時),M代表不可達(注意飛行路徑是單向的,即A–>B不等於B–>A)
例如:
1)從1號城市飛行到4號城市花費5h,從4號城市飛到1號城市花費2h
2)從5號城市飛行到3號城市不可達,從3號城市飛行到5號城市花費7h
這裏寫圖片描述
輸入描述:
輸入出差城市x(x可以是1,2,3,4,6)
輸入大霧城市y(y可以是0,1,2,3,4,5,6,爲0時代表沒有出現大霧)
輸出描述:
輸出最短飛行時間(不可達時爲1000)
輸出飛行路徑,使用“[]”包圍所有值,使用“,”分割數值(不可達時“[]”)
輸入例子:
2
4
輸出例子:
6
[5,1,2]

解題思路:

  1. 如果目標城市和大霧城市是同一個的話,依題意所知,一定不可達
  2. 如果大霧城市就是出發城市的話,依舊不可達
  3. 當沒有城市有大霧,也就是說輸入y=0時,首先設置最低時長爲直達的時間,然後使用回溯法計算從出發城市到目標城市的所有路徑,此路徑包括不可達與可達路徑,當路徑不可達時,我們設置達到時長是M=1000,最後計算所有可能的路徑時長,求最小值
  4. 當有大霧城市的時候,我們計算路徑的時候直接移除該城市的所有路徑的情況,也就是說在計算的路徑的時候直接不考慮該城市。之後的情況也就和上面類似了。
  5. 注意細節,因爲A城市到B城市的時長,與B城市到A城市的時長是不相同的,所以計算路徑的時候,不能僅僅計算子集那麼簡單,還要計算該子集路徑的全排列!
    代碼簡單易懂!歡迎糾正。
    public static void getMinPath(int x,int y){
        int M=1000;
        int [][]matrix={{M,2,10,5,3,M},{M,M,12,M,M,10},{M,M,M,M,7,M}//初始化數組
        ,{2,M,M,M,2,M},{4,M,M,1,M,M},{3,M,1,M,2,M}};
        List<Integer> target=new ArrayList<Integer>();//初始化目標城市
        target.add(1);
        target.add(2);
        target.add(3);
        target.add(4);
        target.add(6);
        if(!target.contains(x)||y>6||y<0){//非法輸入的討論
            System.out.println("非法輸入");
            return;
        }
        if(x==y){//目標城市和大霧城市相同,肯定是不可達
            System.out.println(1000);
            System.out.println("[]");
            return;
        }
        if(y==5){//大霧城市就是出發城市,肯定不可達
            System.out.println(1000);
            System.out.println("[]");
            return;
        }
        if(y==0){//沒有大霧的天氣
            target.remove((Integer)x);
            List<List<Integer>> result=new ArrayList<List<Integer>>();//取子集
            List<Integer> tempList=new ArrayList<Integer>();//臨時存儲
            List<List<Integer>> last=new ArrayList<List<Integer>>();//取所有的路徑情況
            for(int i=1;i<=target.size();i++)
                subSet(target, i, 0, result, tempList); 
            for(int i=0;i<result.size();i++){
                List<Integer> temp=result.get(i);
                rank(temp, tempList, last);
            }
            int min=matrix[4][x-1];//初始值爲直達
            String str="[5,";
            int index=-1;
            for(int i=0;i<last.size();i++){
                List<Integer> temp=last.get(i);
                int sum=matrix[4][temp.get(0)-1];
                for(int j=1;j<temp.size();j++)
                    sum+=matrix[temp.get(j-1)-1][temp.get(j)-1];
                sum+=matrix[temp.get(temp.size()-1)-1][x-1];
                if(min>sum){
                    min=sum;
                    index=i;
                }
            }
            //輸出處理start
            if(index==-1){//如果在直達的情況最小
                if(min==1000){//如果直到最小值是1000的話,則說明這條路徑是沒有的
                    System.out.println(1000);
                    System.out.println("[]");
                }else{//反之輸出直達路徑
                    System.out.println(min);
                    System.out.println(str+(x)+"]");
                }
            }else{
                System.out.println(min);
                for(int i=0;i<last.get(index).size();i++){
                    str+=last.get(index).get(i)+",";
                }
                System.out.println(str+x+"]");
            }
            //輸出處理end
        }else{//有大霧的天氣,但是不是出發點,也不是目的地
            target.remove((Integer)x);
            target.remove((Integer)y);
            List<List<Integer>> result=new ArrayList<List<Integer>>();//取子集
            List<Integer> tempList=new ArrayList<Integer>();//臨時存儲
            List<List<Integer>> last=new ArrayList<List<Integer>>();//取所有的路徑情況
            for(int i=1;i<=target.size();i++)
                subSet(target, i, 0, result, tempList); 
            for(int i=0;i<result.size();i++){
                List<Integer> temp=result.get(i);
                rank(temp, tempList, last);
            }
            int min=matrix[4][x-1];//初始值爲直達
            String str="[5,";
            int index=-1;
            for(int i=0;i<last.size();i++){
                List<Integer> temp=last.get(i);
                int sum=matrix[4][temp.get(0)-1];
                for(int j=1;j<temp.size();j++)
                    sum+=matrix[temp.get(j-1)-1][temp.get(j)-1];
                sum+=matrix[temp.get(temp.size()-1)-1][x-1];
                if(min>sum){
                    min=sum;
                    index=i;
                }
            }
            //輸出處理start
            if(index==-1){
                if(min==1000){
                    System.out.println(1000);
                    System.out.println("[]");
                }else{
                    System.out.println(min);
                    System.out.println(str+(x)+"]");
                }
            }else{
                System.out.println(min);
                for(int i=0;i<last.get(index).size();i++){
                    str+=last.get(index).get(i)+",";
                }
                System.out.println(str+x+"]");
            }
            //輸出處理end
        }
    }

   public static void subSet(List<Integer> target,int k,int start,List<List<Integer>> result,List<Integer> tempList){
        //計算所有的路徑
        if(k<0)
            return;
        else if(k==0){
            result.add(new ArrayList<Integer>(tempList));
        }else{
            for(int i=start;i<target.size();i++){
                tempList.add(target.get(i));
                subSet(target, k-1, i+1, result, tempList);
                tempList.remove(tempList.size()-1);
            }
        }
    }

   public static void rank(List<Integer> list,List<Integer> tempList,List<List<Integer>> result){
        //路徑的全排列
        if(tempList.size()==list.size()){
            result.add(new ArrayList(tempList));
        }else{
            for(int i=0;i<list.size();i++){
                if(tempList.contains(list.get(i)))
                    continue;
                tempList.add(list.get(i));
                rank(list, tempList, result);
                tempList.remove(tempList.size()-1);
            }
        }
    }

2,任務調度過程
題目描述:
輸入五個任務的ID,任務優先級,開始運行時間和運行時長,其中調度過程是搶佔式的,即優先級數值高的任務可以搶佔正在運行的優先級值低的任務,最後輸出前200秒,任務調度過程
輸入描述:
任務信息輸入格式:[任務ID.優先級.任務開始時間.任務時長];任務與任務之間使用“|”隔開,5個任務ID爲1-5;優先級範圍是0-200
輸出描述:
輸出任務信息爲:任務ID.任務時長;任務之間使用“|”隔離;如果無任何任務運行,則任務ID爲0
輸入例子:
[1.80.1.10]|[2.20.11.15]|[3.50.21.10]|[4.123.31.10]|[5.100.41.10]
輸出例子:
0.1|1.10|2.10|3.10|4.10|5.10|2.5|0.144
題目解析:
1,該題目的輸入輸出處理起來相當不易,注意的是”|”和”.”在使用字符串截取的時候都需要轉義字符“\\”;
2,因爲任務是搶佔式的,所以我們處理的時候優先級高者優先處理;
3,我們可以逐秒分析,分析該時刻應該是哪個任務所擁有執行,如果沒有任務執行,則任務id爲0;


廢話不多說,代碼夠詳細!

import java.util.*;
public class FX002 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            String str=sc.nextLine();
            String []arr=str.split("\\|");
            List<Job> list=new ArrayList<Job>();//存放任務
            for(int i=0;i<arr.length;i++){
                String temp=arr[i].substring(1, arr[i].length()-1);
                String []arrTemp=temp.split("\\.");
                int id=Integer.parseInt(arrTemp[0]);
                int priorty=Integer.parseInt(arrTemp[1]);
                int start=Integer.parseInt(arrTemp[2]);
                int lasting=Integer.parseInt(arrTemp[3]);
                Job job=new Job(id, priorty, start, lasting);
                list.add(job);
            }
            List<Job> postSort=sortByPriorty(list);//將任務按照優先級排序
            List<Integer> q=new ArrayList<Integer>();//存放每刻時間的任務id
            for(int i=0;i<200;i++){
                Job currentJob=null;//當前任務
                for(Job job:postSort){
                    if(job.start<=i&&job.left>0){
                        currentJob=job;//選取此刻優先級最高的任務並且該任務剩餘的工作量大於0
                        break;//獲取之後即跳出,以防被低優先級的任務搶去
                    }
                }
                if(currentJob==null){
                    q.add(0);//如果此刻沒有任務,則將此刻id賦值0
                }else{
                    q.add(currentJob.id);//存放任務id
                    currentJob.left--;//該任務的工作量遞減
                }   
            }
            q.add(-1);//存放任務id的鏈表結束符
            String s="";//返回結果
            int count=1;//計數器:在鏈表中連續工作的時間數
            for(int i=0;i<q.size()-1;i++){
                if(q.get(i)==q.get(i+1)){
                    count++;
                }else{
                    s+=q.get(i)+"."+count+"|";
                    count=1;
                }
            }
            System.out.println(s.substring(0, s.length()-1));//輸出結果
        }
    }
    public static List<Job> sortByPriorty(List<Job> list){//任務按優先級排序
        List<Integer> priortyList=new ArrayList<Integer>();
        for(Job j:list)
            priortyList.add(j.priorty);
        Collections.sort(priortyList);
        List<Integer> index=new ArrayList<Integer>();
        for(Integer i:priortyList){
            int start=-1;
            loop:for(Job j:list){
                start++;
                if(i==j.priorty){
                    index.add(start);
                    start=-1;
                    break loop;
                }
            }
        }
        List<Job> postSort=new ArrayList<Job>();
        for(Integer i:index)
            postSort.add((list.get(i)));
        List<Job> result=new ArrayList<Job>();
        for(int i=0;i<postSort.size();i++)
            result.add(postSort.get(postSort.size()-1-i));
        return result;
    }

}
class Job{
    int id;//任務id
    int priorty;//優先級
    int start;//開始時間
    int lasting;//工作時長
    int left;//剩餘工作時長
    public Job(int id,int priorty,int start,int lasting){
        this.id=id;
        this.priorty=priorty;
        this.start=start;
        this.lasting=lasting;
        this.left=lasting;
    }
}

測試樣例,如圖所示:

這裏寫圖片描述

3,IP地址排序
題目描述:
一組IP地址可能包含A,B,C,D,E類型,請按照ip地址類型輸出,相同ip地址類型的按照ip地址的大小排序,按照整數大小從小到達排序。錯誤ip地址不參與排序。
輸入描述:
輸入5行,每行均爲一個ip地址,ip地址可能是錯誤的,錯誤ip地址不參與排序
輸出描述:
輸出N行,每行輸出相同類型的IP地址且按照ip地址大小排序,使用“[]”包圍所有值,使用“,”分割數值
輸入例子:
80.1.1.1
90.1.1.1
180.1.1.1
190.1.1.1
200.1.1.1
輸出描述:
A:[80.1.1.1,90.1.1.1]
B:[180.1.1.1,190.1.1.1]
C:[200.1.1.1]
解題分析:

  1. 第一步要做的就是合法性分析,此題目要求比較低,合法性分析咱們只需要分析其每位數字是否處於0-255之間即可
  2. 將ip地址分類
  3. 因爲是需要對每組的IP地址進行排序,所有我們直接調用Collections.sort(),這給我們省去了很大的麻煩
  4. 當然排序算法如果覺得不可靠的話,可隨意寫了就行。
    廢話不說,直接上代碼!
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class FX003 {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            String s1=sc.nextLine();
            String s2=sc.nextLine();
            String s3=sc.nextLine();
            String s4=sc.nextLine();
            String s5=sc.nextLine();
            List<String> list=new ArrayList<String>();
            list.add(s1);
            list.add(s2);
            list.add(s3);
            list.add(s4);
            list.add(s5);
            classifyIP(list);
        }
    }
    public static void classifyIP(List<String> list){
        List<String> A=new ArrayList<String>();
        List<String> B=new ArrayList<String>();
        List<String> C=new ArrayList<String>();
        List<String> D=new ArrayList<String>();
        List<String> E=new ArrayList<String>();
        for(int i=0;i<list.size();i++){
            if(isValid(list.get(i))){
                String []arr=list.get(i).split("\\.");
                int x=Integer.parseInt(arr[0]);
                if(x>=0&&x<=127)//A
                    A.add(list.get(i));
                else if(x>=128&&x<=191)//B
                    B.add(list.get(i));
                else if(x>=192&&x<=223)//C
                    C.add(list.get(i));
                else if(x>=224&&x<=239)//D
                    D.add(list.get(i));
                else//E
                    E.add(list.get(i));
            }
        }
        if(!A.isEmpty()){
            Collections.sort(A);//排序
            System.out.print("A:");
            System.out.println(A);
        }
        if(!B.isEmpty()){
            Collections.sort(B);
            System.out.print("B:");
            System.out.println(B);
        }
        if(!C.isEmpty()){
            Collections.sort(C);
            System.out.print("C:");
            System.out.println(C);
        }
        if(!D.isEmpty()){
            Collections.sort(D);
            System.out.print("D:");
            System.out.println(D);
        }
        if(!E.isEmpty()){
            Collections.sort(E);
            System.out.print("E:");
            System.out.println(E);
        }
    }
    public static boolean isValid(String s){//題幹中指出:ip地址合法性的判斷答題者只需負責數字的大小驗證
        String []arr=s.split("\\.");
        for(int i=0;i<arr.length;i++){
            if(Integer.parseInt(arr[i])>255||Integer.parseInt(arr[i])<0)
                return false;
        }
        return true;
    }
}

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章