原题:某餐馆有n张桌子,每张桌子有一个参数:a 可容纳的最大人数; 有m批客人,每批客人有两个参数:b人数,c预计消费金额。 在不允许拼桌的情况下,请实现一个算法选择其中一部分客人,使得总预计消费金额最大
卷前:水平太菜,花了好几个小时写到现在,结果到最后时间复杂度超过一秒提交不了(JAVA写的)
卷中:放代码,测试数据在卷尾
class Table implements Comparable<Table> { public int max; public boolean visited; public Table(int max) { this.max = max; } @Override public int compareTo(Table o) { if (o.max > this.max) return 1;// 降序 return -1; } @Override public String toString() { return "Table [max=" + max + ", visited=" + visited + "]"; } } class Guest implements Comparable<Guest> { public int num; public int cost; public boolean isSet = false; public Guest(int num, int cost) { this.num = num; this.cost = cost; } @Override public int compareTo(Guest o) { if (o.num > this.num) { return 1; } else if (o.num == this.num) { if (o.cost > this.cost) { return 1; } else { return -1; } } else { return -1; } } @Override public String toString() { return "Guest [num=" + num + ", cost=" + cost + "]"; } } public class Main { public static void main(String[] args) { Scanner scan = new Scanner(System.in); // 输入n张桌子,m批客人 int n = scan.nextInt(); int m = scan.nextInt(); // 输入n个参数a表示每张桌子可容纳的最大人数 Table[] tables = new Table[n]; Guest[] guests = new Guest[m]; for (int i = 0; i < n; i++) { int a = scan.nextInt(); // System.out.println("第"+(i+1)+"张桌子 最大人数是:"+a); tables[i] = new Table(a); } // 输入m组参数 人数b 预计消费c for (int i = 0; i < m; i++) { int b = scan.nextInt(); int c = scan.nextInt(); // System.out.println("第"+(i+1)+"组 人数:"+b+"消费:"+c); guests[i] = new Guest(b, c); } // Arrays.sort(guests); Arrays.sort(tables); // for(Guest g:guests) { // System.out.println(g); // } // for(Table t:tables) { // System.out.println(t); // } // 遍历桌子,放入人数 int out = 0; boolean isFirst = true; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { // if (guests[i].num <= tables[j].max && !tables[j].visited && !guests[i].isSet) { // 还要看是不是后面有更多钱的 int max = guests[i].cost; for (int temp = i; temp < m; temp++) { if (guests[temp].num <= tables[j].max && !tables[j].visited && !guests[temp].isSet && (j + 1 != n) ? (guests[temp].num > tables[j + 1].max) : true) { if (max < guests[temp].cost) { guests[temp].isSet = true; max = guests[temp].cost; } } } guests[i].isSet = true; tables[j].visited = true; out += max; if (isFirst)// 第一批最肥客人如果没找到合适num桌子就跳下一批否则会直接跳下一桌 isFirst = false; break; } if (isFirst) break; } } // 输出 System.out.println(out); } }
卷后:还得多练习
思路:
- 桌子降序,客源按人数降序、人数相同则按预计花费降序;
- 从第一个最大(a最大)的桌子开始放客。(细节,如果第一次放不到合适的,即isFirst,直接break到下一批客源,否则会break到下一个桌子,导致空桌子);
- 放成功则isVisited,isSet标记;
- 后面的桌子放的时候需要判断是否后面会有更肥(cost更高的)的客源,有就放后面的(细节,后面的客源需要判断下人数guests[temp].num是否小于当前桌子加一(tables[j+1])的桌子大小tables[j+1].max);
- 挨个从高到低杀猪完成(中途后面有肥的就贪婪先杀了…)。
- 全剧终,完了时间复杂度超过1s,提交失败。
测试数据:
3 5
2 4 2
1 3
3 5
3 7
5 9
1 10
答案:20
解析输入:
3 5 #分别为桌子3张,客源5批
2 4 2 #分别为桌子① 2个位置 桌子②4个位置 桌子③2个位置
1 3 #客源①1个人 3单元花费 √
3 5 #客源②3个人 5单元花费 ×
3 7 #客源③3个人 7单元花费 √
5 9 #客源④5个人 9单元花费 ×
1 10 #客源⑤1个人 10单元花费 √