【華為機試線上訓練】Day 10

HelloZEX發表於2018-08-09

自動售貨系統

題目描述

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;
}


 

相關文章