洛谷P2058 海港

题目重述:

输入输出样例:

 

原题链接:原题出自洛谷: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;
}

上述思路代码,如有错误或疑问,欢迎私信!另外如果有更好的思路和解答也请教导。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值