D. [202506F]清羽的自动贩卖机

文件操作

时间限制: 1000ms

空间限制: 262144KB

输入文件名: 202506F.in

输出文件名: 202506F.out

题目背景

清羽购置了一台自动贩卖机放在广场上,这台自动贩卖机有一个用户数据库和商品数据库。
用户数据库记录当前用户的用户名,密码,以及当前充值的余额,并且存在两种用户,管理员和普通用户,管理员当然只有清羽一个人。用户名和密码均为字符串。
商品数据库中记录商品的名字和种类,以及价格、库存和购买次数。商品名字和种类均为字符串,价格为整数。

初始时仅有一个管理员账号,账号密码均为admin,但注意,自动贩卖机一开始没有处于用户登录状态。

这台自动贩卖机有如下操作:

题目描述

  • register注册功能:用户需要输入账号和密码,并且注册的账号不能和用户数据库当中已有的账号相同。
  • login登录功能:使用该功能首先需要用户处在非登录状态,用户需要输入已经注册到用户数据库当中的账号和密码进行登录
  • logout登出功能:可以让用户从当前登录状态下退出登录。
  • recharge充值功能:可以进行充值,自动贩卖机仅支持10元,5元,2元,1元的充值
  • buy购买功能:自动贩卖机可以通过用户充值的余额进行商品的购买
  • change找零功能:自动贩卖机可以将购买商品后剩余的钱通过找零10,5,2,1元的方式退回用户。
  • restock建议补货功能:自动贩卖机会检查当前是否需要补货
  • list商品排列功能:用户可以根据选择进行排列。
  • 如果某次操作指令并不属于上述指令,则返回unknown command

输入格式

第一行输入nn表示自动贩卖机有nn个商品

接下来nn行每行输入namename,categorycategory,priceprice,stockstock,分别表示商品名,商品种类,商品价格和商品的初始库存

接下来一行输入mm表示mm次操作,初始时仅有一个管理员账号,账号密码均为admin,但注意,自动贩卖机一开始没有处于用户登录状态。

在每次操作中:

register操作需要再输入namename和passwordpassword表示注册用户的账号和密码

login操作需要再输入namename和passwordpassword表示登录用户的账号和密码

logout操作表示登出当前账号

recharge操作需要再输入一个整数xx表示当前投币充值的面额

buy操作需要再输入一个namename表示购买的商品名

change操作表示为当前用户余额进行找零

restock操作仅限管理员使用,表示查看是否需要补货

list操作表示排列当前商品,需要再输入一个字符串all表示按照初始输入顺序全部排列,hot表示按照热销进行排列,其余字符串视为种类,表示排列当前种类的商品(按照初始输入顺序排列)

输出格式

register操作中,如果当前输入的用户名存在,则输出user exists,否则完成注册输出register ok

login操作如果已经处于登录情况则输出logged in,如果登录成功输出user in,否则输入login failed

logout操作如果用户并没有处于登录状态输出user out,在登出时,如果用户还有余额需要对用户找钱,仅限找零面额为[10,5,2,1][10,5,2,1]由大到小输出,例如找零13元可以输出change: 10x1 2x1 1x1change: 后面格式为【面额】x【数量】,如果用户没有余额则不用找零。退出后输出user out

recharge操作如果用户未登录输入please login,如果用户充值面额并非[1,2,5,10][1,2,5,10]输出:invalid coin;充值完毕后输出"balance: +当前用户余额。

buy操作如果用户未登录输入please login,如果输入的商品未找到输出product not found, 如果当前商品库存不够输出sold out,并退出。如果用户余额不够输出not enough money。购买完毕后输出buy +商品名

change操作为用户登录状态下的找零操作,如果用户未登录输入please login,如果用户如果有余额输出与logout操作输出类似,如果没有余额,输出00

restock操作如果用户未登录输入please login,如果用户非管理员输出not Admin,之后遍历所有商品,如果存在库存少于3个的情况输出yes否则输出no

list操作如输出格式所述,如果输入字符串为all或其他种类字符串,输出每行分别显示当前商品的名字,种类,价格,库存和购买数量。如果输入字符串为hot执行对所有商品按照购买次数进行从大到小的稳定排序,如果购买次数相同按照商品名的字典序从小到大进行稳定排序。排序买行显示当前商品和当前购买次数,中间用空格隔开

样例

Input 1

5 a c1 1 10 b c2 2 10 c c1 1 10 d c2 3 10 e c2 1 10 12 register user1 123456 login admin admin recharge 10 buy b change list hot logout restock login user1 123456 buy c restock login admin admin

Output 1

register ok user in balance: 10 buy b change: 5x1 2x1 1x1 b 1 a 0 c 0 d 0 e 0 user out please login user in not enough money not Admin logged in

数据范围

样例nm性质
1−31−3≤10≤10≤30≤30样例仅有管理员账号和购买操作
4−54−5≤10≤10≤1000≤1000样例包含有其他账号
6−76−7≤10≤10≤3000≤3000样例包含有检查是否有库存和找零操作
8−108−10≤10≤10≤3000≤3000样例包含有排列操作

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int N = 1e3 + 5;

struct User {
	string name;
	string pwd;
	bool isAdmin;
	int blance;
} user[N];

struct Product {
	string name;
	string category;
	int price;
	int stock;
	int cnt;
} product[N], tmp[N];

int usercnt, productCnt;
int checkUser = -1;

int coin[] = {10, 5, 2, 1};

void reg(string n, string p) {
	for (int i = 1; i <= usercnt; i++) {
		if (user[i].name == n) {
			cout << "user exists\n";
			return ;
		}
	}
	user[++usercnt] = {n, p, 0, 0};
	cout << "register ok\n";
}

void login(string n, string p) {
	if (checkUser != -1) {
		cout << "logged in\n";
		return ;
	}

	for (int i = 1; i <= usercnt; i++) {
		if (user[i].name == n && user[i].pwd == p) {
			checkUser = i;
			cout << "user in\n";
			return ;
		}
	}

	cout << "login failed\n";
}

void logout() {
	if (checkUser == -1) {
		cout << "user out\n";
		return ;
	}

	//退出时自动找零
	int bal = user[checkUser].blance;
	if (bal > 0) {
		cout << "change:";
		int res = bal;
		for (int i = 0; i < 4; i++) {
			int cnt = res / coin[i];
			res %= coin[i];
			if (cnt > 0) {
				cout << " " << coin[i] << "x" << cnt;
			}
		}
		cout << '\n';
		user[checkUser].blance = 0;
	}
	checkUser = -1;
	cout << "user out\n";
}

//充值
void recharge(int amt) {
	if (checkUser == -1) {
		cout << "please login\n";
		return ;
	}

	if (amt != 1 && amt != 2 && amt != 5 && amt != 10) {
		cout << "invalid coin\n";
		return ;
	}

	user[checkUser].blance += amt;
	cout << "balance: " << user[checkUser].blance << '\n';
}

void cmd_rank() {
	for (int i = 1; i <= productCnt; i++) {
		tmp[i] = product[i];
	}
	stable_sort(tmp + 1, tmp + 1 + productCnt, [](Product a, Product b) {
		if (a.cnt != b.cnt) return a.cnt > b.cnt;
		return a.name < b.name;
	});

	for (int i = 1; i <= productCnt; i++) {
		cout << tmp[i].name << ' ' << tmp[i].cnt << '\n';
	}
}

void buyproduct(string n) {
	if (checkUser == -1) {
		cout << "please login\n";
        return;
	}

	int idx = -1;
	
	for (int i = 1; i <= productCnt; i++) {
		if (product[i].name == n) {
			idx = i;
			break;
		}
	}

	if (idx == -1) {
		cout << "product not found\n";
		return ;
	}

	Product &p = product[idx];
	if (p.stock <= 0) {
        cout << "sold out\n";
        return;
    }

	if (user[checkUser].blance < p.price) {
		cout << "not enough money\n";
		return ;
	}

	user[checkUser].blance -= p.price;
	p.stock--;
	p.cnt++;

	cout << "buy " << p.name << '\n';
}

void restock() {
	if (checkUser == -1) {
		cout << "please login\n";
        return;
	}

	if (!user[checkUser].isAdmin) {
		cout << "not Admin\n";
		return ;
	}

	bool need = 0;
	//如果有小于3件商品就需要补货建议
	for (int i = 1; i <= productCnt; i++) {
		if (product[i].stock <= 3) {
			need = 1;
			break;
		}
	}
	cout << (need ? "yes" : "no") << '\n';
}

void cmt_list(string arg) {
	if (arg == "all") {
		//全部列出
		for (int i = 1; i <= productCnt; i++) {
			Product &p = product[i];
			cout << p.name << ' ' << p.category 
				<< ' ' << p.price << ' ' << p.stock 
				<< ' ' << p.cnt << '\n';
		}
	} else if (arg == "hot") {
		cmd_rank();
	} else {
		for (int i = 1; i <= productCnt; i++) {
			Product &p = product[i];
			if (p.category == arg) {
				cout << p.name << ' ' << p.category 
				<< ' ' << p.price << ' ' << p.stock 
				<< ' ' << p.cnt << '\n';
			}
		}
	}
}

int main(void)
{
	freopen("202506F.in", "r", stdin);
	freopen("202506F.out", "w", stdout);
	int n;
	cin >> n;
	productCnt = n;
	for (int i = 1; i <= n; i++) {
		cin >> product[i].name
			>> product[i].category
			>> product[i].price
			>> product[i].stock;
		product[i].cnt = 0;
	}

	user[++usercnt] = {"admin", "admin", 1, 0};

	int m;
	cin >> m;

	while (m--) {
		string op;
		cin >> op;
		string n, p;
		if (op == "register") {
			cin >> n >> p;
			reg(n, p);
		} else if (op == "login") {
			cin >> n >> p;
			login(n, p);
		} else if (op == "logout") {
			logout();
		} else if (op == "recharge") {
			int amt;
			cin >> amt;
			recharge(amt);
		} else if (op == "buy") {
			string name;
			cin >> name;
			buyproduct(name);
		} else if (op == "change") {
			if (checkUser == -1) {
                cout << "please login\n";
            } else {
				int bal = user[checkUser].blance;
				if (bal > 0) {
					cout << "change:";
					int res = bal;
					for (int i = 0; i < 4; i++) {
						int cnt = res / coin[i];
						res %= coin[i];
						if (cnt > 0) {
							cout << " " << coin[i] << "x" << cnt;
						}
					}
					cout << '\n';
					user[checkUser].blance = 0;
				} else {
					cout << "0\n";
				}
			}
		} else if (op == "restock") {
			restock();
		} else if (op == "list") {
			string arg;
			cin >> arg;
			cmt_list(arg);
		} else {
			cout << "unknown command\n";
		}
	}


	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值