有n个人正在饭堂排队买海北鸡饭。每份海北鸡饭要25元。奇怪的是,每个人手里只有一张钞票(每张钞票的面值为25、50、100元)……

 问题描述
  有n个人正在饭堂排队买海北鸡饭。每份海北鸡饭要25元。奇怪的是,每个人手里只有一张钞票(每张钞票的面值为25、50、100元),而且饭堂阿姨一开始没有任何零钱。请问饭堂阿姨能否给所有人找零(假设饭堂阿姨足够聪明)
输入格式
  第一行一个整数n,表示排队的人数。

接下来n个整数a[1],a[2],…,a[n]。a[i]表示第i位学生手里钞票的价值(i越小,在队伍里越靠前)
输出格式
  输出YES或者NO
样例输入
4
25 25 50 50
样例输出
YES
样例输入
2
25 100
样例输出
NO
样例输入
4
25 25 50 100
样例输出
YES
数据规模和约定
  n不超过1000000

测试用例1:
4
25 50 50 50

测试用例2:

6

25 25 50 100 100 25

 

这个题是蓝桥杯的一道vip题,也是我当时蓝桥时练习的一道,在昨天也是收到消息问我这个代码不容易读,确实,让我现在看我也有点迷,不过不能就这样放着不管不是,怎么也要让大家知道问题。

先来看我原来写的吧,我只说一下我的思路,因为代码确实没啥注释,不好理解,I am so sorry!

我当时思路其实就是暴力破解了,首先考虑就是如果我第一个用户来消费,直接给100,食堂阿姨肯定很无奈,破不开,然后没事了,不过发现后面有个假设饭堂阿姨足够聪明,那不就完事了呗,我直接把钱都收过来,然后分配,看你需要找几块,我就给你呗,如果找不开,那不就说明找钱不成功么。

那么我刚开始的算法就有点菜了,相当于我首先定义一个数组,然后把数组里的数据装入List里面,因为list操作比较简单,说简单是因为其底层的扩容机制,其实就是数据结构方面的知识。然后我用list去计算钱是否够,先看25的够不,然后看50的,然后看100的,依次循环遍历比较,确实当时都不知道为啥会想到这种方法,还给各位客观老爷们头苦,一脸懵逼,你这代码连个注释也没有。

那么今天我也是又从新写了一下,其实思路比较简单的

1. 还是把所有钱都收过来

2. 计算各种钱的数量,比如标记25的,50的,100的分别有多少

3. 我们会发现只需要考虑两种,当是25时,我直接收就完事了,当是50,那么我直接移除为25的,然后添加50的,当是100的时候,考虑3张25和1张25+1张50的情况。

这是我刚才又写的一个,这种代码简单一些,思路跟上面的一样

import java.util.Scanner;
public class FindMoney {
 public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        //a1,a2,a3代表 25 ,50,100的数量
        int a1 = 0, a2 = 0, a3 = 0;
        for (int i = 0; i < n; i++) {
            int temp = sc.nextInt();
            if (temp == 25) {
                a1++;
            } else if (temp == 50) {
                a2++;
            } else if (temp == 100) {
                a3++;
            }
        }
        System.out.println(a1 + " " + a2 + " " + a3);
        //50 直接用25的减
        a1 = a1 - a2;
        //判断a1是否大于0
        if (a1 >= 0) {
            if ( a1 / 3 >= a3  ){
                System.out.println("YES");
            } //判断 25 +50
            else if (a2*50+a1*25>=(a3*75)){
                System.out.println("YES");
            }else {
                System.out.println("NO");
            }
        } else {
            System.out.println("NO");
        }

    }
}

下面是我以前写的,也不删了,就当做我前后学习的对比吧,对于这种题,我今天其实第一反应就是贪心,也发现算法做多了,其实也是有规律可言的,也愿大家以后对于算法题不紧张,理清思路,找到解题策略,从而把题目拿下!

思路:

一个数组存储n个人的费用,另一个集合来存所要找的零钱,考虑顺序

代码:

import java.util.ArrayList;
import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = sc.nextInt();
        }
        System.out.println(test(arr, list));
    }

    public static String test(int[] arr, ArrayList<Integer> list) {
        int keyi=0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == 25) {
                list.add(arr[i]);
                keyi++;
            
            } else if (arr[i] == 50) {
                for (int j = 0; j < list.size(); j++) {
                    if (list.get(j) == 25) {
                        list.remove(j);
                        list.add(50);
                        keyi++;
                        break;
                    }

                }
            }
            else if (arr[i] == 100) {
                int twenteFive=0;
                int fifty=0;
                for (int j = 0; j<list.size(); j++) {
                    if(list.get(j)==25) {
                        twenteFive++;
                    }else if(list.get(j)==50) {
                        fifty++;
                    }
                }

                if(twenteFive>=3 || fifty>=1&&twenteFive>=1) {
                    if(fifty>=1&&twenteFive>=1) {
                        for (int j = 0; j < list.size(); j++) {
                            if(list.get(j)==25) {
                                list.remove(j);
                                break;
                            }
                        }
                        
                        for (int j = 0; j <list.size(); j++) {
                            if(list.get(j)==50) {
                                list.remove(j);
                                break;
                            }
                        }
                        keyi++;
                        
                    }
                    else if(twenteFive>=3) {
                    
                        for (int j = 0; j <3; j++) {
                            for (int j2 = 0; j2 < list.size(); j2++) {
                                if(list.get(j2)==25) {
                                    list.remove(j2);
                                    break;
                                }
                            }
                        }
                        keyi++;
                        
                    
                    }
                }
            }
        }


        if (keyi==arr.length){
            return "YES";
        }else {
            return "NO";
        }


    }
}

 

A)观察者模式的模式模型: 观察者模式是一种行为设计模式,它允许对象在发生状态变化时通知其他对象。在观察者模式中,有两种类型的对象:主题和观察者。主题是状态变化的对象,观察者是接收主题状态变化通知的对象。当主题状态发生变化时,它会通知所有的观察者,让它们能够更新自己的状态。 观察者模式的模式模型包括以下几个角色: 1. 抽象主题(Subject):定义了主题的接口,包括添加、删除和通知观察者的方法。 2. 具体主题(ConcreteSubject):实现了抽象主题接口,维护了一个观察者列表,并在状态发生变化时通知观察者。 3. 抽象观察者(Observer):定义了观察者的接口,包括更新状态的方法。 4. 具体观察者(ConcreteObserver):实现了抽象观察者接口,保存了一个指向具体主题的引用,并在接收到通知时更新自己的状态。 B)场景实现: 下面是一个基于观察者模式的美食产生器场景实现的示例代码: ```python # 抽象主题 class FoodGenerator: def __init__(self): self.observers = [] def add_observer(self, observer): self.observers.append(observer) def remove_observer(self, observer): self.observers.remove(observer) def notify_observers(self, food): for observer in self.observers: observer.update(food) # 具体主题 class MiniFoodGenerator(FoodGenerator): def __init__(self): super().__init__() def generate_food(self): # 随机产生一道美食 food = random.choice(['广味腊肠饭', '湛江鸡饭', '美味烤蚝', '雪域冰城糖水']) # 通知所有观察者 self.notify_observers(food) # 抽象观察者 class Observer: def update(self, food): pass # 具体观察者 class Student(Observer): def __init__(self, name, favorite_food): self.name = name self.favorite_food = favorite_food def update(self, food): if food == self.favorite_food: print(f'{self.name}:我喜欢的{food}出锅了!') else: print(f'{self.name}:我不喜欢的{food}出锅了。') # 场景实现 if __name__ == '__main__': # 创建迷你美食产生器 generator = MiniFoodGenerator() # 创建学生观察者 student1 = Student('小明', '广味腊肠饭') student2 = Student('小红', '湛江鸡饭') student3 = Student('小刚', '美味烤蚝') student4 = Student('小芳', '雪域冰城糖水') # 添加观察者 generator.add_observer(student1) generator.add_observer(student2) generator.add_observer(student3) generator.add_observer(student4) # 产生美食 generator.generate_food() ``` 在上面的代码中,我们定义了一个抽象主题 `FoodGenerator`,它包括添加、删除和通知观察者的方法。然后我们定义了一个具体主题 `MiniFoodGenerator`,它继承了抽象主题,并实现了随机产生美食的方法。当产生美食时,它会通知所有的观察者。 我们还定义了一个抽象观察者 `Observer`,它定义了更新状态的方法。然后我们定义了一个具体观察者 `Student`,它继承了抽象观察者,并实现了更新状态的方法。当收到通知时,它会判断是否是自己喜欢的美食,如果是就欢呼一声,否则就不理会。 在场景实现中,我们创建了一个迷你美食产生器 `generator`,并添加了四个学生观察者。然后我们调用 `generator.generate_food()` 方法产生美食,这时所有的观察者都会收到通知,并根据自己的口味判断是否喜欢这道美食。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值