题目描述
要求停车场有M个入口,P个出口,停车场共有N个车位,其中每5个车位为一个小型立体车库,先来后到原则进行入场,入场后开始进行计费。若停车场满了之后,门口的车一次排队,出来一辆车之后,放行一辆车再入场。要求:
1)每个入口使用队列结构模拟排队场景,排序车辆需要记录排队时间,根据时间先后进场放行。
2)每个小型立体车库只用散列表进行模拟入库及出库。
3)计费原则:15分钟以下免费,超过15分钟按0.5元/15分钟。小型车夜间停车1元/小时。
案例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_QUEUE_SIZE 100
#define MAX_PARKING_SPOTS 20
#define SMALL_GARAGE_SIZE 5
#define PARKING_RATE 0.5 // 超过15分钟按0.5元/15分钟计费
#define NIGHT_PARKING_RATE 1.0 // 小型车夜间停车1元/小时
// 定义车和时间的结构体
typedef struct Car {
char license_plate[10]; // 车牌号
time_t arrival_time; // 入场时间
} Car;
// 定义停车场的结构体
typedef struct ParkingLot {
int num_entrances; // 入口数量
int num_exits; // 出口数量
int num_spots; // 停车位总数
int num_small_garages; // 小型立体车库数量
Car *spots[MAX_PARKING_SPOTS]; // 停车位数组,每个元素指向一辆车
int num_free_spots; // 空闲车位数
int free_small_garages[SMALL_GARAGE_SIZE]; // 空闲小型立体车库编号
// 入口队列数组
struct Queue {
Car *data[MAX_QUEUE_SIZE];
int front, rear;
int size;
} *entrance_queues;
// 出口队列数组
struct Queue {
Car *data[MAX_QUEUE_SIZE];
int front, rear;
int size;
} *exit_queues;
// 散列表结构体
struct Hashtable {
Car *data[MAX_PARKING_SPOTS / SMALL_GARAGE_SIZE][SMALL_GARAGE_SIZE];
} *garages;
} ParkingLot;
// 计算两个时间之间的差值(单位:秒)
int time_diff(time_t start, time_t end) {
return (int)difftime(end, start);
}
// 初始化停车场
void init_parking_lot(ParkingLot *lot, int num_entrances, int num_exits, int num_spots, int num_small_garages) {
lot->num_entrances = num_entrances;
lot->num_exits = num_exits;
lot->num_spots = num_spots;
lot->num_small_garages = num_small_garages;
lot->num_free_spots = num_spots;
memset(lot->spots, 0, sizeof(lot->spots));
memset(lot->free_small_garages, 0, sizeof(lot->free_small_garages));
lot->entrance_queues = (struct Queue*)malloc(num_entrances * sizeof(struct Queue));
lot->exit_queues = (struct Queue*)malloc(num_exits * sizeof(struct Queue));
lot->garages = (struct Hashtable*)malloc(sizeof(struct Hashtable));
for (int i = 0; i < num_entrances; i++) {
lot->entrance_queues[i].front = 0;
lot->entrance_queues[i].rear = -1;
lot->entrance_queues[i].size = 0;
}
for (int i = 0; i < num_exits; i++) {
lot->exit_queues[i].front = 0;
lot->exit_queues[i].rear = -1;
lot->exit_queues[i].size = 0;
}
for (int i = 0; i < num_small_garages; i++) {
lot->free_small_garages[i] = i;
}
for (int i = 0; i < num_spots / SMALL_GARAGE_SIZE; i++) {
for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
lot->garages->data[i][j] = NULL;
}
}
}
// 入场
void enter_parking_lot(ParkingLot *lot, int entrance_index, Car *car) {
// 判断是否有空闲车位
if (lot->num_free_spots == 0) {
printf("Parking lot is full, car %s has to wait.\n", car->license_plate);
printf("Car %s is waiting at entrance %d.\n", car->license_plate, entrance_index);
lot->entrance_queues[entrance_index].rear++;
lot->entrance_queues[entrance_index].data[lot->entrance_queues[entrance_index].rear] = car;
lot->entrance_queues[entrance_index].size++;
return;
}
// 找到一辆空闲的停车位
int spot_index;
if (lot->num_free_spots >= SMALL_GARAGE_SIZE) {
// 如果有足够的连续空闲车位,就使用小型立体车库
for (int i = 0; i < lot->num_small_garages; i++) {
if (lot->free_small_garages[i] + SMALL_GARAGE_SIZE <= lot->num_spots && lot->spots[lot->free_small_garages[i]] == NULL) {
spot_index = lot->free_small_garages[i];
for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
lot->spots[spot_index + j] = car;
}
for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
lot->garages->data[spot_index / SMALL_GARAGE_SIZE][j] = car;
}
for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
lot->free_small_garages[i + j] = -1;
}
lot->num_free_spots -= SMALL_GARAGE_SIZE;
break;
}
}
} else {
// 否则使用普通停车位
for (int i = 0; i < lot->num_spots; i++) {
if (lot->spots[i] == NULL) {
spot_index = i;
lot->spots[spot_index] = car;
lot->num_free_spots--;
break;
}
}
}
printf("Car %s enters parking lot at spot %d.\n", car->license_plate, spot_index);
}
// 出场
void exit_parking_lot(ParkingLot *lot, int exit_index) {
// 判断是否有等待的车辆
if (lot->exit_queues[exit_index].size > 0) {
Car *car = lot->exit_queues[exit_index].data[lot->exit_queues[exit_index].front];
lot->exit_queues[exit_index].front++;
lot->exit_queues[exit_index].size--;
printf("Car %s exits parking lot from exit %d.\n", car->license_plate, exit_index);
// 计算停车费用
int time_diff_sec = time_diff(car->arrival_time, time(NULL));
double cost = 0.0;
if (time_diff_sec <= 900) { // 15分钟以下免费
cost = 0.0;
} else {
cost = PARKING_RATE * (time_diff_sec / 900.0); // 超过15分钟按0.5元/15分钟计费
}
if (cost == 0.0) {
printf("Car %s parked for free.\n", car->license_plate);
} else {
printf("Car %s parked for %d seconds, cost %.2f yuan.\n", car->license_plate, time_diff_sec, cost);
}
// 释放停车位或者小型立体车库
if (lot->spots[spot_index] != NULL) {
lot->spots[spot_index] = NULL;
lot->num_free_spots++;
} else {
int garage_index = spot_index / SMALL_GARAGE_SIZE;
for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
lot->garages->data[garage_index][j] = NULL;
}
for (int j = 0; j < SMALL_GARAGE_SIZE; j++) {
lot->free_small_garages[spot_index + j / SMALL_GARAGE_SIZE] = spot_index + j;
}
lot->num_free_spots += SMALL_GARAGE_SIZE;
}
}
}
// 模拟停车场的运行
void simulate_parking_lot(ParkingLot *lot) {
while (1) {
// 从入口队列中取出一辆车
for (int i = 0; i < lot->num_entrances; i++) {
if (lot->entrance_queues[i].size > 0) {
Car *car = lot->entrance_queues[i].data[lot->entrance_queues[i].front];
// 判断是否可以进入停车场
if (lot->num_free_spots > 0) {
enter_parking_lot(lot, i, car);
// 从入口队列中删除该车辆
lot->entrance_queues[i].front++;
lot->entrance_queues[i].size--;
}
break;
}
}
// 从出口队列中取出一辆车
for (int i = 0; i < lot->num_exits; i++) {
if (lot->exit_queues[i].size > 0) {
exit_parking_lot(lot, i);
break;
}
}
// 随机生成一辆车并加入到某个入口的队列中
int entrance_index = rand() % lot->num_entrances;
Car *car = (Car*)malloc(sizeof(Car));
sprintf(car->license_plate, "ABC-%03d", rand() % 1000);
car->arrival_time = time(NULL);
printf("New car %s arrives at entrance %d.\n", car->license_plate, entrance_index);
lot->entrance_queues[entrance_index].rear++;
lot->entrance_queues[entrance_index].data[lot->entrance_queues[entrance_index].rear] = car;
lot->entrance_queues[entrance_index].size++;
// 等待一段时间
sleep(1);
}
}
int main() {
srand(time(NULL));
ParkingLot lot;
init_parking_lot(&lot, 2, 2, 20, 4);
simulate_parking_lot(&lot);
return 0;
}
我们首先定义了一个Car
结构体来表示车的信息,包括车牌号和入场时间。然后,我们定义了一个ParkingLot
结构体来表示整个停车场的信息,包括入口数量、出口数量、停车位总数、小型立体车库数量等。在ParkingLot
结构体中,我们使用三个数组来分别表示停车位、入口队列和出口队列,使用散列表来表示小型立体车库。其中,入口队列和出口队列都是用队列结构来实现的。
在init_parking_lot
函数中,我们初始化了停车场的信息。在enter_parking_lot
函数中,我们模拟了车辆进入停车场的过程,根据停车位的状态判断车辆是否可以进入停车场,如果停车场已满,则将该车辆加入到对应入口的队列中。在exit_parking_lot
函数中,我们模拟了车辆离开停车场的过程,根据车辆的停留时间计算停车费用,并释放对应的停车位或小型立体车库。在simulate_parking_lot
函数中,我们不断循环执行以下三个操作:从入口队列中取出一辆车并判断是否可以进入停车场、从出口队列中取出一辆车并将其出场、随机生成一辆车并加入到某个入口的队列中。
在main
函数中,我们首先调用srand
函数来初始化随机数生成器,然后使用init_parking_lot
函数来初始化停车场,最后调用simulate_parking_lot
函数来模拟停车场的运行。