在赛码网上看到的2016年的京东实习生在线编程题,赛码网上将其难度划为最高之一,于是就做了一下。
赛码网不让转载题目,原题目在这:http://exercise.acmcoder.com/online/online_judge_ques?ques_id=3816&konwledgeId=41
整体思路与hashmap的思路有点类似,
每一个信封都是一个Entry类,
它内部还包含它的下一个最优Entry(保持嵌套信封数最多)。
内部还包含了所有比他大的信封entry所组成的arraylist(利用这些entry来计算出哪一个装此entry可达到嵌套数最多)
/** * Created by CLY on 2017年4月23日. */ package pers.cly.algorithm.birthday_gift; import java.util.ArrayList; import java.util.Iterator; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { int line_num = scanner.nextInt(); long card_x_size= scanner.nextLong(); int card_y_size = scanner.nextInt(); ArrayList<Entry> sumList = new ArrayList<>(); for (int i = 0; i < line_num; i++) { long now_x = scanner.nextLong(); int now_y = scanner.nextInt(); //信封必须大于卡片 if (now_x>card_x_size&&now_y>card_y_size) { Entry now_entry = new Entry(); now_entry.set_index(i+1); now_entry.set_mailer_x_size(now_x); now_entry.set_mailer_y_size(now_y); sumList.add(now_entry); //将当前entry与以存的entry进行大小的比较 for(Entry old_entry :sumList){ long old_x = old_entry.get_mailer_x_size(); int old_y = old_entry.get_mailer_y_size(); if (old_x>now_x&&old_y>now_y) {//旧信封比当前信封大 now_entry.get_more_big_entry().add(old_entry); }else if (now_x>old_x&&now_y>old_y) {//当前信封比旧信封大 old_entry.get_more_big_entry().add(now_entry); } } } } Entry start_mail=null; int sum = 0; //如果有比信件大的信封 if (sumList.size()>=1) { Iterator<Entry> iterator = sumList.iterator(); //先计算第一个entry的最优嵌套数,然后再和其他entry的最优嵌套数比对 do { Entry now_entry = iterator.next(); int now_len = now_entry.get_best_len(); if (now_len!=0) {//拥有最优嵌套数 if (now_len>sum) { sum = now_len; start_mail = now_entry; } }else {//还未计算最优嵌套数,现在计算 now_len = calculate_best_len(now_entry); if (now_len>sum) { sum = now_len; start_mail = now_entry; } } } while (iterator.hasNext()); System.out.println(sum); System.out.print(start_mail.get_index()+" "); Entry next_entry = start_mail.get_best_choose(); while (next_entry!=null) { System.out.print(next_entry.get_index()+" "); next_entry = next_entry.get_best_choose(); } }else {//没有合适的信封 System.out.println(sum); } } } /** * 计算某entry的最优嵌套数 * @param arrayList * @return 最优嵌套数 */ private static int calculate_best_len(Entry target_entry) { ArrayList<Entry> arrayList = target_entry.get_more_big_entry(); int target_best_len=1; Entry target_best_choose=null; //如果target_entry拥有子list(比他大的entry),则迭代找到最大的len for (Entry entry : arrayList) { int son_best_len = entry.get_best_len(); //如果该子entry也没有最优嵌套数,则先计算他的最优嵌套数 if (son_best_len==0) { son_best_len = calculate_best_len(entry); } son_best_len++;//加上本entry后的总嵌套数 if (son_best_len>target_best_len) { target_best_len = son_best_len; target_best_choose = entry; } } target_entry.set_best_choose(target_best_choose); target_entry.set_best_len(target_best_len); return target_best_len; } } class Entry{ int index;//是第几个出现的 long mailer_x_size; int mailer_y_size; ArrayList<Entry> more_big_entry; Entry best_choose;//选择哪一个信封可以达到最多嵌套数 //当选择了当前卡片后,前套数最多能加几(当前entry如果没有计算过,则为0,计算过后至少为1) int best_len; public Entry() { this.index=0; this.mailer_x_size=0; this.mailer_y_size=0; this.best_len = 0; this.best_choose = null; this.more_big_entry= new ArrayList<>(); } public void set_index(int index) { this.index=index; } public void set_mailer_x_size(long mailer_x_size) { this.mailer_x_size=mailer_x_size; } public void set_mailer_y_size(int mailer_y_size) { this.mailer_y_size=mailer_y_size; } public void set_best_choose(Entry entry) { this.best_choose = entry; } public void set_best_len(int best_len) { this.best_len = best_len; } public int get_index() { return this.index; } public long get_mailer_x_size() { return this.mailer_x_size; } public int get_mailer_y_size() { return this.mailer_y_size; } public ArrayList<Entry> get_more_big_entry() { return this.more_big_entry; } public Entry get_best_choose() { return this.best_choose; } public int get_best_len() { return this.best_len; } }