【华为机试在线训练】Day 10

2023-11-17

自动售货系统

题目描述

1 总体说明

考生需要模拟实现一个简单的自动售货系统,实现投币、购买商品、退币、查询库存商品及存钱盒信息的功能。

系统初始化时自动售货机中商品为6种商品,商品的单价参见1.1规格说明,存钱盒内放置1元、2元、5元、10元钱币,商品数量和钱币张数通过初始化命令设置,参见2.1 系统初始化。

1.1规格说明

1. 商品:每种商品包含商品名称、单价、数量三种属性,其中商品名不重复。考生不能修改商品名称和单价,初始化命令设置商品数量。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。

商品 名称

单价

数量

A1 2 X
A2 3 X
A3 4 X
A4 5 X
A5 8 X
A6 6 X

2. 存钱盒信息:钱币面额、张数两种属性。初始化命令设置各种面额钱币张数。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。

钱币面额

张数

10元

X

5元

X
2元 X
1元 X

3. 退币原则 

1) 根据系统存钱盒内钱币的 信息 ,按钱币总张数最少的原则进行退币。

2) 如果因零钱不足导致不能退币,则尽最大可能退币,以减少用户损失。

例如:假设存钱盒内只有4张2元,无其它面额钱币。如果需要退币7元,系统因零钱不足无法退币,则继续尝试退币6元,最终系统成功退币3张2元,用户损失1元钱币。

4. 投币操作说明:每次投币成功,投入的钱币面额累加到投币余额;同时,本次投入的钱币放入存钱盒中,存钱盒相应面额钱币增加。

5. 投币余额:指当前自动售货机中用户剩余的可购买商品的钱币总额;例如:投入2元面额的钱币,投币余额增加2元;购买一件价格2元的商品,投币余额减少2元;

6. 投币余额约束:投币余额不能超过10元。

7. 退币操作说明:退币操作需要遵守 退币原则 ;退币成功后,投币余额清零,同时扣除存钱盒相应的金额。

8. 购买商品操作说明:一次仅允许购买一件商品;购买商品成功后,自动售货机中对应商品数量减1,投币余额扣除本次购买商品的价格。

2 操作说明

命令字与第一个参数间使用一个空格分隔,多条命令采用分号隔开。考试系统会对输入命令格式进行处理,考生不需要关注输入命令格式的合法性,只需要实现命令处理函数。

2.1 系统初始化

命令格式

r A1 数量 -A2 数量 -A3 数量 -A4 数量 -A5 数量 -A6 数量 元张数 -2 元张数 -5 元张数 -10 元张数

参数名称

参数说明

类型

取值范围

A1数量

商品A1数量

整数

[0,10]

A2数量

商品A2数量

整数

[0,10]

A3数量

商品A3数量

整数

[0,10]

A4数量

商品A4数量

整数

[0,10]

A5数量

商品A5数量

整数

[0,10]

A6数量

商品A6数量

整数

[0,10]

1元张数

面额1元钱币张数

整数

[0,10]

2元张数

面额2元钱币张数

整数

[0,10]

5元张数

面额5元钱币张数

整数

[0,10]

10元张数

面额10元钱币张数

整数

[0,10]

商品和各种面额钱币取值范围只是作为初始化命令的限制,其它场景下不限制取值范围;考试框架已经实现取值范围的检查,考生不需要关注。

功能说明:设置自动售货机中商品数量和存钱盒各种面额的钱币张数;

约束说明:系统在任意阶段均可执行r初始化系统;考生不需要关注参数的合法性,不需要关注增加或缺少参数的场景;

输出说明:输出操作成功提示(执行完r命令后系统会自动输出操作结果,考生不需要再次调用输出函数),例:

命令 输出 含义
r 6-5-4-3-2-1 4-3-2-1; S001:Initialization is successful 初始化成功

2.2 投币

命令格式钱币面额

功能说明

(1) 如果投入非1元、2元、5元、10元的钱币面额(钱币面额不考虑负数、字符等非正整数的情况),输出“E002:Denomination error”;

(2) 如果存钱盒中1元和2元面额钱币总额小于本次投入的钱币面额,输出“E003:Change is not enough, pay fail”,但投入1元和2元面额钱币不受此限制。

(3) 如果投币余额大于10元,输出“E004:Pay the balance is beyond the scope biggest”;

(4) 如果自动售货机中商品全部销售完毕,投币失败。输出“E005:All the goods sold out”;

(5) 如果投币成功,输出“S002:Pay success,balance=X”;

约束说明

(1) 系统在任意阶段都可以投币;

(2) 一次投币只能投一张钱币;

(3) 同等条件下,错误码的优先级:E002 > E003 > E004 > E005;

输出说明:如果投币成功,输出“S002:Pay success,balance=X”。

例:

命令

输出

p 10;

S002:Pay success,balance=10

2.3 购买商品

命令格式商品名称

功能说明

(1) 如果购买的商品不在商品列表中,输出“E006:Goods does not exist”;

(2) 如果所购买的商品的数量为0,输出“E007:The goods sold out”;

(3) 如果投币余额小于待购买商品价格,输出“E008:Lack of balance”;

(4) 如果购买成功,输出“S003:Buy success,balance=X”;

约束说明

(1) 一次购买操作仅能购买一件商品,可以多次购买;

(2) 同等条件下,错误码的优先级:E006 > E007 > E008;

输出说明:

如果购买成功,输出“S003:Buy success,balance=X”。

例:

命令

输出

b A1;

S003:Buy success,balance=8

2.4 退币

命令格式c

功能说明

(1) 如果投币余额等于0的情况下,输出“E009:Work failure”;

(2) 如果投币余额大于0的情况下,按照 退币原则 进行“找零”,输出退币信息;

约束说明

(1) 系统在任意阶段都可以退币;

(2) 退币方式必须按照 退币原则 进行退币;

输出说明:如果退币成功,按照 退币原则 输出退币信息。

例,退5元钱币:

命令

输出

c;

1 yuan coin number=0

2 yuan coin number=0

5 yuan coin number=1

10 yuan coin number=0

2.5 查询

命令格式q 查询类别

功能说明

(1) 查询自动售货机中商品信息,包含商品名称、单价、数量。 根据商品数量从大到小进行排序;商品数量相同时,按照商品名称的先后顺序进行排序 

例如:A1的商品名称先于A2的商品名称,A2的商品名称先于A3的商品名称。

(2) 查询存钱盒信息,包含各种面额钱币的张数;

(3) 查询类别如下表所示:

查询类别

查询内容

0

查询商品信息

1 查询存钱盒信息

如果“查询类别”参数错误,输出“E010:Parameter error”。“查询类别”参数错误时,不进行下面的处理;

输出说明

“查询类别”为0时,输出自动售货机中所有商品信息(商品名称单价数量)例:

命令

输出

q 0;

A1 2 6

A2 3 5

A3 4 4

A4 5 3

A5 8 2

A6 6 0

“查询类别”为1时,输出存钱盒信息(各种面额钱币的张数),格式固定。例:

命令

输出

q 1;

1 yuan coin number=4

2 yuan coin number=3

5 yuan coin number=2

10 yuan coin number=1

输入描述:

依照说明中的命令码格式输入命令。

输出描述:

输出执行结果

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
       
using namespace std;
int A_num[]={0,0,0,0,0,0,0};//货的数目
int A_price[]={0,2,3,4,5,8,6};//货的价格
int M_num[]={0,0,0,0};//钱币数目
int M[]={1,2,5,10};//钱币面值
int pay=0;//付的钱数
     
     
void process(string str,int pos);
   
   
int main()
{
    int i,k,tmp,len;
    string  str;
    while (getline(cin,str))
    {
        cout<<"S001:Initialization is successful"<<endl;//初始化成功
        tmp=0;
        k=1;
        for(i=2;str[i]!=' ';i++)//取货的个数
        {
            if(str[i]=='-'){A_num[k++]=tmp;tmp=0;}
            else if(isdigit(str[i]))tmp=tmp*10+str[i]-'0';
        }
        A_num[k]=tmp;
        len=i;//保存空格位置
        k=0;
        tmp=0;
        for(i=len;str[i]!=';';i++)//取钱的个数
        {
            if(str[i]=='-'){M_num[k++]=tmp;tmp=0;}
            else if(isdigit(str[i]))tmp=tmp*10+str[i]-'0';
        }
        M_num[k]=tmp;
        pay=0;//初始清零
        for(i=13;i<str.size();i++)//功能处理
        {
            if((i+1)<str.size()&&str[i]==';')
            process(str,i+1);
        }
    }
       
    return 0;
}
     
     
void process(string str,int pos)
{
    int i,tmp=0;
    switch(str[pos])
    {
        case 'p'://付钱
        for(i=pos+2;str[i]!=';';i++)
        {
            tmp=tmp*10+str[i]-'0';
        }
     
        if(tmp!=1&&tmp!=2&&tmp!=5&&tmp!=10)cout<<"E002:Denomination error"<<endl;
        else
        {
            if(tmp>2&&(M_num[0]+2*M_num[1])<tmp)cout<<"E003:Change is not enough, pay fail"<<endl;
            else if(tmp>10)cout<<"E004:Pay the balance is beyond the scope biggest"<<endl;
            else if(A_num[3]==0&&A_num[2]==0&&A_num[1]==0&&A_num[0]==0)cout<<"E005:All the goods sold out"<<endl;
            else
            {
                pay+=tmp;
                switch(tmp)
                {
                case 1:M_num[0]++;cout<<"S002:Pay success,balance="<<pay<<endl;break;
                case 2:M_num[1]++;cout<<"S002:Pay success,balance="<<pay<<endl;break;
                case 5:M_num[2]++;cout<<"S002:Pay success,balance="<<pay<<endl;break;
                case 10:M_num[3]++;cout<<"S002:Pay success,balance="<<pay<<endl;break;
                default:break;
                }
            }
        }
    break;
    case 'q'://查询
    tmp=str[pos+2]-'0';
    if(tmp==0)
    {
        for(i=1;i<=6;i++)cout<<"A"<<i<<" "<<A_price[i]<<" "<<A_num[i]<<endl;
    }
    else if(tmp==1)
    {
        for(i=0;i<4;i++)cout<<M[i]<<" yuan coin number="<<M_num[i]<<endl;
    }
    else cout<<"E010:Parameter error";
    break;
    case 'b'://买商品
    tmp=str[pos+3]-'0';
    if(tmp>=1&&tmp<=6)
    {
        if(A_num[tmp]==0)cout<<"E007:The goods sold out"<<endl;
        else if(pay<A_price[tmp])cout<<"E008:Lack of balance"<<endl;
        else {pay-=A_price[tmp];cout<<"S003:Buy success,balance="<<pay<<endl;A_num[tmp]--;}
    }
    else
    cout<<"E006:Goods does not exist"<<endl;
    break;
    case 'c'://找钱退币
    if(pay==0)cout<<"E009:Work failure";
    else
    {
        int cnt[4]={0,0,0,0};
        while((pay-10)>=0&&M_num[3]>0){pay-=10;M_num[3]--;cnt[3]++;}
        while((pay-5)>=0&&M_num[2]>0){pay-=5;M_num[2]--;cnt[2]++;}
        while((pay-2)>=0&&M_num[1]>0){pay-=2;M_num[1]--;cnt[1]++;}
        while((pay-1)>=0&&M_num[0]>0){pay-=1;M_num[0]--;cnt[0]++;}
        for(i=0;i<4;i++)cout<<M[i]<<" yuan coin number="<<cnt[i]<<endl;
        pay=0;
    }
    break;
    default:
    break;
    }
}


Redraiment的走法

题目描述

题目描述 

   Redraiment是走梅花桩的高手。Redraiment总是起点不限,从前到后,往高的桩子走,但走的步数最多,不知道为什么?你能替Redraiment研究他最多走的步数吗? 

样例输入

6

2 5 1 5 4 5

样例输出

3

提示

Example: 
6个点的高度各为 2 5 1 5 4 5 
如从第1格开始走,最多为3步, 2 4 5 
从第2格开始走,最多只有1步,5 
而从第3格开始走最多有3步,1 4 5 
从第5格开始走最多有2步,4 5

所以这个结果是3。

接口说明

方法原型:

    int GetResult(int num, int[] pInput, List  pResult);

输入参数:
   int num:整数,表示数组元素的个数(保证有效)。
   int[] pInput: 数组,存放输入的数字。

输出参数:
   List pResult: 保证传入一个空的List,要求把结果放入第一个位置。
返回值:
  正确返回1,错误返回0

输入描述:

输入多行,先输入数组的个数,再输入相应个数的整数

输出描述:

输出结果

#include<iostream>
#include<stdio.h>
#include<vector>
 
using namespace std; //动态规划
 
int main(){
    int N;
    while(cin>>N){
        vector<int> Data(N,0);
        vector<int> Dp(N,1);
        int ret = 0;
        for(int i=0; i<N; ++i){
            cin >> Data[i];
            for(int j=0; j<i; j++){
                if(Data[i]>Data[j])
                    Dp[i] = max(Dp[i],Dp[j]+1);
            }
            ret = max(ret,Dp[i]);
        }
        cout<< ret<<endl;
    }
    return 0;
}


求解立方根

题目描述

•计算一个数字的立方根,不使用库函数

详细描述:

•接口说明

原型:

public static double getCubeRoot(double input)

输入:double 待求解参数

返回值:double  输入参数的立方根,保留一位小数

输入描述:

待求解参数 double类型

输出描述:

输入参数的立方根 也是double类型

/*
牛顿迭代法。设f(x)=x3-y, 求f(x)=0时的解x,即为y的立方根。
根据牛顿迭代思想,xn+1=xn-f(xn)/f'(xn)即x=x-(x3-y)/(3*x2)=(2*x+y/x/x)/3;
*/
#include <stdio.h>
inline double abs(double x){return (x>0?x:-x);}
double cubert(const double y){
    double x;
    for(x=1.0;abs(x*x*x-y)>1e-7;x=(2*x+y/x/x)/3);
    return x;
}
int main(){
    for(double y;~scanf("%lf",&y);printf("%.1lf\n",cubert(y)));
    return 0;
}


求最小公倍数

题目描述

正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。

输入描述:

输入两个正整数A和B。

输出描述:

输出A和B的最小公倍数。

/* c++
最小公倍数 = 两数之积除以最大公约数
*/
#include<iostream>
using namespace std;
 
int gcd(int a, int b) // greatest common divisor
{
    while(a%b){
        int tmp = a;
        a = b;
        b = tmp%b;
    }
    return b;
 
}
int main()
{
    int a,b;
    while(cin >> a >> b){
        cout << a*b/gcd(a,b) <<endl;
    }
    return 0;
}


DFS优先搜索

题目描述

编写一个函数,传入一个int型数组,返回该数组能否分成两组,使得两组中各元素加起来的和相等,并且,所有5的倍数必须在其中一个组中,所有3的倍数在另一个组中(不包括5的倍数),能满足以上条件,返回true;不满足时返回false。 

输入描述:

第一行是数据个数,第二行是输入的数据

输出描述:

返回true或者false

#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <assert.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <numeric>
using namespace std;

bool DFS(vector<int> &nums, vector<bool> &visited, int sum)
{
	if (sum == 0) return true;
	for (int i = 0; i < visited.size(); ++i)
	{
		if (visited[i] == false)
		{
			visited[i] = true;
			if (DFS(nums, visited, sum - nums[i]))
				return true;
			visited[i] = false;
		}
	}
	return false;
}

int main(void)
{
	int n, tmp;
	while (cin >> n)
	{
		bool flag = true;
		vector<int> array_rest;
		vector<int> array_5;
		vector<int> array_3;
		for (int i = 0; i < n; ++i)
		{
			cin >> tmp;
			if (tmp % 5 == 0)
				array_5.push_back(tmp);
			else if (tmp % 3 == 0)
				array_3.push_back(tmp);
			else
				array_rest.push_back(tmp);
		}
		// 首先对3组数据求和,分别是3的倍数,5的倍数和剩下的
		int sum_3 = std::accumulate(array_3.begin(), array_3.end(), 0);
		int sum_5 = std::accumulate(array_5.begin(), array_5.end(), 0);
		int sum_rest = std::accumulate(array_rest.begin(), array_rest.end(), 0);
		int diff = abs(sum_3 - sum_5);
		// 然后用深度优先遍历找到是否存在解,
		// 因为2*x + diff = sum_rest
		// 所以x = [sum_rest-diff]/2     
		// 因此用深度遍历找到array_rest中是否存在和为x的一组数就可以了
		if ((sum_rest - diff) % 2 != 0)
		{
			flag = false; // 不能整除就无解
		}
		else
		{
			int goal = (sum_rest - diff) / 2;
			vector<bool> visited(array_rest.size(), false);
			if (!DFS(array_rest, visited, goal))
				flag = false;
		}
		if (flag)
			cout << "true" << endl;
		else
			cout << "false" << endl;
	}
	return 0;
}


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【华为机试在线训练】Day 10 的相关文章

随机推荐