题目重述:
输入输出样例:
原题链接:原题出自洛谷:P2058 海港
分析:
这道题首先要求我们输入n艘船的信息,每艘船的信息包括:这艘船的入港时间t,乘客数量k,剩下的是乘客信息X1,X2...Xk。
对于这道题,我们可以利用一个长度为k的数组来存储乘客信息,下标i存储Xi+1(i=0,1...k)的乘客信息。
之后对于每艘船,我们要统计在这一天内到达海港的所有乘客类型的个数。通俗点来讲,就是对于第j艘船,和所有符合 “tj-86400<tp<=tj”的船p,统计这些船上所有乘客的类型,返回所有乘客的类型数。若乘客为1,2,3,5.则输出4.
为了统计乘客类型,我们可以利用哈希表来统计每种乘客的数量,最后对于所有非0的乘客进行计数,最后输出。
这里的哈希表我选择使用两种形式进行实现。
1.数组实现哈希
2.链表实现哈希
因为某些数据,其乘客类型跨度可能很大,例如乘客类型为:1,2,1000,10000,这种情况利用数组实现哈希就会造成极大的空间浪费。而对于一些数据类型很多的数据,例如乘客类型为:1,2,3,4,...,999,1000,1001,这种情况对于链表实现的哈希就会导致查询时浪费大量时间.
两种方法各有所优,可以看实际情况进行选取.
代码:(C语言)
1.数组实现哈希
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct shipmessage//存储船的信息
{
int time;
int num;
int* datas;
}ship;
ship init_ship(int time, int num)//初始化船,输入时间time,乘客数num
{
ship x;
x.time = time;
x.num = num;
x.datas = (int*)malloc(sizeof(int) * num);
return x;
}
int max(int* nums, int numsSize)//辅助函数,找到数组nums中的最大值
{
int res = nums[0];
int i;
for (i = 1; i < numsSize; i++)
{
if (nums[i] > res)res = nums[i];
}
return res;
}
int main()
{
int ships;//获得船的数量
scanf("%d", &ships);
ship* ship_s = (ship*)malloc(sizeof(ship) * ships);//开辟船数组,储存ships个船的信息
int i;
for (i = 0; i < ships; i++)
{
int time;
int num;
scanf("%d", &time);
scanf("%d", &num);
ship_s[i] = init_ship(time, num);//初始化
int j;
for (j = 0; j < num; j++)
{
scanf("%d", &ship_s[i].datas[j]);//输入乘客信息
}
}
for (i = 0; i < ships; i++)
{
int j;
int res = 0;
int k;
int len = max(ship_s[i].datas, ship_s[i].num);
for (j = 0; j < i; j++)
{
int len1 = max(ship_s[j].datas, ship_s[j].num);
if (len1 > len)len = len1;
}//找到符合条件的船内,所有乘客中的最大值,利用这个最大值开辟哈希表数组
int* hash = (int*)malloc(sizeof(int) * (len + 1));
//由于题目说过,乘客的信息数据不会超过10000,
//所以也可以选择下面的形式开辟hash数组
//int hash[10001];
for (k = 0; k < len + 1; k++)
{
hash[k] = 0;
}
for (j = 0; j < i; j++)
{
if (ship_s[j].time <= ship_s[i].time && ship_s[j].time > ship_s[i].time - 86400)
{
for (k = 0; k < ship_s[j].num; k++)
{
if (hash[ship_s[j].datas[k]] == 0)
{
res++;
}
hash[ship_s[j].datas[k]]++;
}
}
}
for (k = 0; k < ship_s[i].num; k++)
{
if (hash[ship_s[i].datas[k]] == 0)
{
res++;
}
hash[ship_s[i].datas[k]]++;
}
free(hash);
printf("%d\n", res);
}
return 0;
}
2.链表实现哈希
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef struct shipmessage//存储船的信息
{
int time;
int num;
int* datas;
}ship;
typedef struct Node//链表结点
{
int data;
struct Node* next;
}Node, * LinkList;
ship init_ship(int time, int num)//初始化船
{
ship x;
x.time = time;
x.num = num;
x.datas = (int*)malloc(sizeof(int) * num);
return x;
}
bool in_list(LinkList list, int value)//判断值value是否在链表list中,在则输出true,否则输出false
{
if (list == NULL)return false;
Node* p = list;
while (p && p->data != value)
{
p = p->next;
}
if (p != NULL && p->data == value)return true;
else return false;
}
LinkList insert(LinkList list, int value)//插入(这里为了优化代码运行时间,使用头插法)
{
if (list == NULL)
{
list = (Node*)malloc(sizeof(Node));
list->data = value;
list->next = NULL;
return list;
}
else
{
Node* s = (Node*)malloc(sizeof(Node));
s->data = value;
s->next = list;
list = s;
return list;
}
}
int main()
{
int ships;
scanf("%d", &ships);
ship* ship_s = (ship*)malloc(sizeof(ship) * ships);
int i;
for (i = 0; i < ships; i++)
{
int time;
int num;
scanf("%d", &time);
scanf("%d", &num);
ship_s[i] = init_ship(time, num);
int j;
for (j = 0; j < num; j++)
{
scanf("%d", &ship_s[i].datas[j]);
}
}
for (i = 0; i < ships; i++)
{
int j;
int res = 0;
LinkList hash = NULL;
int k;
for (j = 0; j < i; j++)
{
if (ship_s[j].time <= ship_s[i].time && ship_s[j].time > ship_s[i].time - 86400)
{
for (k = 0; k < ship_s[j].num; k++)
{
if (!in_list(hash, ship_s[j].datas[k]))
{
res++;
hash = insert(hash, ship_s[j].datas[k]);
}
}
}
else
{
continue;
}
}
for (k = 0; k < ship_s[i].num; k++)
{
if (!in_list(hash, ship_s[i].datas[k]))
{
res++;
hash = insert(hash, ship_s[i].datas[k]);
}
}
printf("%d\n", res);
}
return 0;
}
上述思路代码,如有错误或疑问,欢迎私信!另外如果有更好的思路和解答也请教导。