1. 程式人生 > >滴滴打車2017招聘筆試題

滴滴打車2017招聘筆試題

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

有個一個飯店,有n張桌子,每張桌子可以招待不同數量的客人,且不能拼桌,現在來了m批客人,每批客人有兩個屬性,一個是客人的總數,一個是他們消費(預計)的總額

請設計一個演算法,計算出,店家能夠獲得的最大利潤


我自己設計了一個演算法,是這麼思考的,先把客人排序,按照消費比(就是消費的金額除以人數)排序,然後吧桌子也排序

首先安排消費比最高的客人,從最小的桌子開始安排,如果桌子太小了,就換一個比它大一點的桌子

程式碼如下:


import java.util.ArrayList;import java.util.Collections;import java.util.List;import java.util.Scanner;class Table2 implements Comparable<Table2>int m; boolean
used; int fee; public Table2(int count){  m=count; } @Override public int compareTo(Table2 o) {  if (o.m>=m) {   return -1;  }else {   return 1;  }   }}class Person implements Comparable
<Person>
int count; int fee; double rate; boolean zhaodai; public void computeRate(){  rate=fee*1.0/count; } public Person(int count,int fee){  this.count=count;  this.fee=fee; } @Override public int compareTo(Person o) {  if (o.rate>=rate) {   return 1;  }else {   return -1;  } } public String toString(){  return count+" "+" "+fee+" "+rate; }}public class Main public static void main(String[] args) {  int n,m;    Scanner sc=new Scanner(System.in);  n=sc.nextInt();  m=sc.nextInt();    List<Table2> nList=new ArrayList<>();  for (int i = 0; i < n; i++) {   Table2 table=new Table2(sc.nextInt());   nList.add(table);  }  Collections.sort(nList);  List<Person> pList=new ArrayList<>();  for (int i = 0; i < m; i++) {   Person person=new Person(sc.nextInt(),sc.nextInt());   person.computeRate();   pList.add(person);  }    Collections.sort(pList);//  for (int i = 0; i < pList.size(); i++) {//   System.out.println(pList.get(i));//  }    for (int i = 0; i < pList.size(); i++) {   Person person=pList.get(i);   if (!person.zhaodai) {    for (int j = 0; j < nList.size(); j++) {          Table2 t=nList.get(j);     if (!t.used) {      if (person.count<t.m) {       t.used=true;       t.fee=person.fee;       person.zhaodai=true;       break;      }     }         }   }  }  int sum=0;  for (int j = 0; j < nList.size(); j++) {   Table2 t=nList.get(j);   sum+=t.fee;  }  System.out.println(sum);     }}/*3 52 4 21 33 53 75 9 1 10    */
上面的測試用例

3 5代表一共有3個桌子 5批客人

2 4 2 代表3張桌子的容量 分別是2 4 2

後面的1 3 代表第一批客人是1個人 消費3元 然後是第二批客人,共3人消費5元

這個測試用例 最後的答案是20


這個思路,是很直觀的,但是,我沒辦法判斷它的正確性

其實它是錯的

輸入:
1 2
4
2 4
3 5
輸出:
4
可答案應該是5才對,因為題目要求的是總消費最高

感謝網友yg33717 



後來,西安交大的張晨同學說,咱們用遞迴試試

思想就是 我隨意讓一個客人佔用一張桌子(當然,至少客人得坐得下)計算一下收益率,然後把剩下的人和剩下的桌子遞迴呼叫安排的程式碼,就OK

我和我的小夥伴們都驚呆了,還能這麼寫

然後 過了20分鐘,他給我發來這個下面的程式碼

import java.util.ArrayList;import java.util.Scanner;/** * Created by zhangchen([email protected]) on 2016/9/7. */public class TableGuest public static void main(String[] args) {  Scanner scanner = new Scanner(System.in);  int tableCount = 0;  int groupCount = 0;  while (scanner.hasNextLine()) {   tableCount = scanner.nextInt();   groupCount = scanner.nextInt();   ArrayList<Table> tables = new ArrayList<>();   ArrayList<GuestGroup> groups = new ArrayList<>();   for (int i = 0; i < tableCount; i++) {    tables.add(new Table(scanner.nextInt()));   }   for (int j = 0; j < groupCount; j++) {    groups.add(new GuestGroup(scanner.nextInt(), scanner.nextInt()));   }   int maxMoney = getMaxMoney(tables, groups);   System.out.println(maxMoney);  } } public static int getMaxMoney(ArrayList<Table> tables,   ArrayList<GuestGroup> groups) {  boolean[] isTableEmpty = new boolean[tables.size()];  boolean[] isGroupWait = new boolean[groups.size()];  for (int i = 0; i < isTableEmpty.length; i++) {   isTableEmpty[i] = true;  }  for (int j = 0; j < isGroupWait.length; j++) {   isGroupWait[j] = true;  }  int maxMoney = assignTable(tables, groups, isTableEmpty, isGroupWait,    tables.size(), groups.size());  return maxMoney; } public static int assignTable(ArrayList<Table> tables,   ArrayList<GuestGroup> groups, boolean[] isTableEmpty,   boolean[] isGroupWait, int tableLeft, int groupLeft) {  if (tableLeft == 0 || groupLeft == 0) {   return 0;  }  int[][] values = new int[tables.size()][groups.size()];// 第i行j列表示將table                // i分配給group j                // 產生的價值  for (int i = 0; i < tables.size(); i++) {   for (int j = 0; j < groups.size(); j++) {    Table table = tables.get(i);    GuestGroup group = groups.get(j);    if (isTableEmpty[i] && isGroupWait[j]      && table.getCapacity() >= group.getGuestCount()) { // 可以嘗試分配     boolean[] isTableEmptyCurrent = isTableEmpty.clone();     boolean[] isGroupWaitCurrent = isGroupWait.clone();     isTableEmptyCurrent[i] = false;     isGroupWaitCurrent[j] = false;     values[i][j] = group.getMoney()       + assignTable(tables, groups, isTableEmptyCurrent,         isGroupWaitCurrent, tableLeft - 1,         groupLeft - 1);    }   }  }  int maxMoney = 0;  for (int i = 0; i < tables.size(); i++) {   for (int j = 0; j < groups.size(); j++) {    if (values[i][j] > maxMoney) {     maxMoney = values[i][j];    }   }  }  return maxMoney; }}class Table public Table(int capacity) {  this.capacity = capacity; } public int getCapacity() {  return capacity; } public void setCapacity(int capacity) {  this.capacity = capacity; } private int capacity;}class GuestGroup public GuestGroup(int guestCount, int money) {  this.money = money;  this.guestCount = guestCount; } private int guestCount; private int money; public int getGuestCount() {  return guestCount; } public void setGuestCount(int guestCount) {  this.guestCount = guestCount; } public int getMoney() {  return money; }}


過了一會,他又說,夥計,夥計,我又有了新的想法,

有一個二維矩陣,m[i][j]=k表示第i這個桌子招待第j批客人,獲得的收益是k元

然後,這個矩陣的每一行,每一列都只能選一個元素

最後求最大值

他問我:你不覺得這程式碼,很熟悉麼?

我看了看,恩,感覺有點像八皇后問題,對呀,他把所有符合規則的排練都求出來,找出最大的 不就OK了麼

子曰:子曰:不憤不啟,不悱不發.舉一隅不與三隅反,則不復也

張晨自己能把這個問題聯絡到八皇后上,牛逼呀

賢哉,晨也!

程式碼如下:


import java.util.ArrayList;import java.util.HashMap;import java.util.Map.Entry;import java.util.Scanner;/** * Created by zhangchen([email protected]) on 2016/9/7. */public class TableGuest2 {    public static void main(String[] args){        Scanner scanner=new Scanner(System.in);        int tableCount=0;        int groupCount=0;        while(scanner.hasNextLine()){            tableCount=scanner.nextInt();            groupCount=scanner.nextInt();            ArrayList<Table> tables=new ArrayList<>();            ArrayList<GuestGroup> groups=new ArrayList<>();            for(int i=0;i<tableCount;i++){                tables.add(new Table(scanner.nextInt()));            }            for(int j=0;j<groupCount;j++){                groups.add(new GuestGroup(scanner.nextInt(),scanner.nextInt()));            }            int[][] assignmentMatrix=new int[tables.size()][groups.size()];            //將問題轉化為在一個矩陣中,每行選擇一個元素,這些元素不能在同一列,使得和最大            for(int i=0;i<tables.size();i++){                for(int j=0;j<groups.size();j++){                    Table table=tables.get(i);                    GuestGroup group=groups.get(j);                    if(table.getCapacity() >= group.getGuestCount()){                        assignmentMatrix[i][j] = group.getMoney(); //可以獲利                    }else { //不能分配                        assignmentMatrix[i][j]=0;                    }                }            }//            int maxMoney= getMaxMoney(tables, groups);            int maxMoney= getMaxMoney(assignmentMatrix);            System.out.println(maxMoney);        }    }    public static int getMaxMoney(ArrayList<Table> tables, ArrayList<GuestGroup> groups){        boolean[] isTableEmpty=new boolean[tables.size()];        boolean[] isGroupWait=new boolean[groups.size()];        for(int i=0;i<isTableEmpty.length;i++){            isTableEmpty[i]=true;        }        for(int j=0;j<isGroupWait.length;j++){            isGroupWait[j]=true;        }        HashMap<Integer,Integer> bestAssignment=assignTable(tables,groups,isTableEmpty,isGroupWait,tables.size(),groups.size());        for(Entry<Integer,Integer> assign:bestAssignment.entrySet()){            System.out.println("將第"+assign.getKey()+"桌分配給"+assign.getValue()+"組客戶");        }        return calculateMoney(groups,bestAssignment);    }    public static int getMaxMoney(int[][] assignmengMatrix){        int rowCount=assignmengMatrix.length;        int colCount=assignmengMatrix[0].length;        ArrayList<int[]> results=new ArrayList<>();        assignTable(0,new int[rowCount],rowCount,colCount,results);        int maxMoney=0;        int[] bestAssignment = new int[rowCount];        for(int[] columns:results){            int total=0;            for(int row=0;row<rowCount;row++){                total+=assignmengMatrix[row][columns[row]];            }            if(total>maxMoney){                maxMoney=total;                bestAssignment=columns;            }        }        for(int i=0;i<bestAssignment.length;i++){            System.out.println("將第"+i+"桌分配給"+bestAssignment[i]+"組客戶");        }        return maxMoney;    }    public static void assignTable(int row,int[] columns,int rowCount,int colCount,ArrayList<int[]> results){        if(row == rowCount){//找到有效的分配方案            results.add(columns.clone());        }else{            for(int col=0;col<colCount;col++){                if(checkValid(columns,row,col)){ //分配是否有效                    columns[row]=col; //分配桌子                    assignTable(row+1,columns,rowCount,colCount,results);                }            }        }    }    public static boolean checkValid(int[] columns,int row1,int col1){        for(int row2=0;row2<row1;row2++){            int col2=columns[row2];            if(col2==col1){ //某一組客戶被重複分配                return false;            }        }        return true;    }    public static HashMap<Integer,Integer> assignTable(ArrayList<Table> tables, ArrayList<GuestGroup> groups,boolean[] isTableEmpty,boolean[] isGroupWait,int tableLeft,int groupLeft){        HashMap<Integer,Integer> bestAssignment=new HashMap<>();        if(tableLeft==0 || groupLeft ==0 ){            return bestAssignment;        }        int maxMoney=0;        for(int i=0;i<tables.size();i++){            for(int j=0;j<groups.size();j++){                Table table=tables.get(i);                GuestGroup group=groups.get(j);                if(isTableEmpty[i] && isGroupWait[j] && table.getCapacity()>=group.getGuestCount()){ //可以嘗試分配                    boolean[] isTableEmptyCurrent=isTableEmpty.clone();                    boolean[] isGroupWaitCurrent=isGroupWait.clone();                    isTableEmptyCurrent[i]=false;                    isGroupWaitCurrent[j]=false;                    HashMap<Integer,Integer> assighment=assignTable(tables, groups, isTableEmptyCurrent, isGroupWaitCurrent,tableLeft-1,groupLeft-1);                    assighment.put(i,j);                    int money=calculateMoney(groups,assighment);                    if(money>maxMoney){                        bestAssignment=assighment;                        maxMoney=money;                    }                }            }        }        return bestAssignment;    }    public static int calculateMoney(ArrayList<GuestGroup> groups,HashMap<Integer,Integer> assignment){        int total=0;        for(int groupIndex:assignment.values()){            total+=groups.get(groupIndex).getMoney();        }        return total;    }}


///////////////////////////////
以下為2016-9-14日補充
感謝"麥爾"對我文章的研究:
非常簡單的問題,怎麼搞得這麼複雜,說明你的演算法功底還很弱,繼續加油學習哦,去TopCoder刷刷題

這個題如果你想到按個人消費排序你就完了,它要的收益最大,不在乎讓最多的人就餐。
演算法思路:
1.將總消費讓從大到小排序 -- consume[m]
2.將桌子按容納人數從小到大排序 -- capacity[n]
3.遍歷consume[m],取出元素後,再從capacity[n]中找到大於或等於該元素人數的桌子,並在capacity[n]標記該桌已用,若沒有桌子能容納該批客則直接放棄該批客人。

就這麼簡單,考慮的是盈利最大,不是要考慮讓更多的人就餐
最後想說我是一個三本學生...
哎怎麼說呢,感覺讀書把自己讀傻了,這個問題本來就很生活化,回家問我不懂計算機的老媽,她估計都能想到這個方法,
我們這些研究生生卻想到那麼複雜的解法,真是讀書讀傻了,這是智商問題呀
以上為2016-9-14日補充
///////////////////////////////




           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述