首页 > 其他 > 详细

航空公司VIP客户查询【PAT】

时间:2014-03-31 06:09:50      阅读:668      评论:0      收藏:0      [点我收藏+]

5-06. 航空公司VIP客户查询

 时间限制  
100 ms
内存限制  
32000 kB
代码长度限制  
8000 B
判题程序    
Standard    

不少航空公司都会提供优惠的会员服务,当某顾客飞行里程累积达到一定数量后,可以使用里程积分直接兑换奖励机票或奖励升舱等服务。现给定某航空公司全体会员的飞行记录,要求实现根据身份证号码快速查询会员里程积分的功能。

输入格式说明:

输入首先给出两个正整数N(<=105)和K(<=500)。其中K是最低里程,即为照顾乘坐短程航班的会员,航空公司还会将航程低于K公里的航班也按K公里累积。随后N行,每行给出一条飞行记录。飞行记录的输入格式为:“18位身份证号码(空格)飞行里程”。其中身份证号码由17位数字加最后一位校验码组成,校验码的取值范围为0~9和x共11个符号;飞行里程单位为公里,是(0, 15 000]区间内的整数。然后给出一个正整数M(<=105),随后给出M行查询人的身份证号码。

输出格式说明:

对每个查询人,给出其当前的里程累积值。如果该人不是会员,则输出“No Info”。每个查询结果占一行。

样例输入与输出:

序号 输入 输出
1
4 500
330106199010080419 499
110108198403100012 15000
120104195510156021 800
330106199010080419 1
4
120104195510156021
110108198403100012
330106199010080419
33010619901008041x
800
15000
1000
No Info

 

 

#include<iostream>
#include<stdio.h>

#include<time.h>

#include<ctype.h>

#include<algorithm>

#include<string.h>

#include<queue>

#include<vector>

using namespace std;

typedef long int lld;//long int

#define rot(v) (((v)>>3)|(((v)&7)<<9))

 

const int MAX=110000;

const int MOD=100003;

const int INF=1000000000;

struct Node

{

    int a,b;

    char x;

    int mile,next;

}node[MAX];

int head[MOD],E;

char buf[22];

int chg(char x)

{

    if(x==‘x‘)return 10;

    return x-‘0‘;

}

int fun(char s[],int &a,int &b,char &x)

{

    int ret=0,i;

    int tmp;

    a=b=0;

    for(i=0;i<9;i++)

    {

        tmp=s[i]-‘0‘;

        a=a*10+tmp;//记录没取余数的数值

        ret=ret*10+tmp;

    }

    ret%=MOD;

    for(;i<17;i++)

    {

        tmp=s[i]-‘0‘;

        b=b*10+tmp;//记录后面没取余数的数值

        ret=(ret*10+tmp)%MOD;

    }

    x=s[i];//记录最后一位

    return (ret*100+chg(s[i]))%MOD;//返回取余数的数值

}

void ins(char s[],int mile)

{

    int a,b;

    char x;

    int h=fun(s,a,b,x);

    int i;

    //发生冲突时的处理 

    for(i=head[h];i!=-1;i=node[i].next)//head 全局变量

    {

        if(node[i].x==x&&node[i].a==a&&node[i].b==b)

        {

            node[i].mile+=mile;

            return ;

        }

    }

    node[E].a=a;

    node[E].b=b;

    node[E].x=x;

    node[E].mile=mile;

    node[E].next=head[h];

    head[h]=E++;

}

 

int query(char s[])

{

    int a,b;

    char x;

    int h=fun(s,a,b,x);

    int i;

    for(i=head[h];i!=-1;i=node[i].next)

    {

        if(node[i].x==x&&node[i].a==a&&node[i].b==b)return node[i].mile;

    }

    return -1;

}

void out(int n)

{

    if(n)

    {

        out(n/10);

        putchar(‘0‘+n%10);

    }

}

int main()

{

    int n,m;

    int k,i;

 

    while(scanf("%d%d",&n,&k)!=EOF)

    {

        memset(head,-1,sizeof(head));

        E=0;

        int mile=0;

        while(n--)

        {

            scanf("%s%d",buf,&mile);

            if(mile<k)mile=k;

            ins(buf,mile);

        }

        scanf("%d",&m);

        getchar();

        while(m--)

        {

            //scanf("%s",buf);

            gets(buf);

            mile=query(buf);

            if(mile==-1)puts("No Info");

            else

            {

                out(mile);
			//	cout<<mile;
			//	printf("%d",mile);

                putchar(‘\n‘);

            }

        }

    }

 

    return 0;

}


解题报告:题目要求的查询次数可能有105的数量级。时间只有100ms 所以一般顺序查询算法是不能满足要求的。这时候就想到了Hash查询,键值对应结果的查询算法。

即使明确了思路,本题依然存在一下难点:

【1】如何选取适当的Hash函数,构造键值对。

【2】我们要知道任何Hash函数都会存在冲突的问题,即:多组查询结果对应同一个键值,如何解决冲突。

【3】如何在有限的时间限制下找到方法进一步优化程序。

 

【1】关于函数的选取尝试了几个方法,如果不侦查冲突的话,一般的取余数算法不能满足要求,折叠取余数算法也不行。最后采取的是累加取余数+冲突检测。

【2】要进行冲突检测就必须有足够的数据特征来区别不同的数值。根据本题的特点我们选取前9位的和a和后9位的和b以及最后一位x,还有键值h四个值来标识一个数值。

但是这样存储数据的数据结构就必须要使用结构体。所以我们构建了一个结构体node,包括a,b,x,next,mile。其中next用于存放发生冲突时的下一个数组下标。正常情况下一个键值对应一个数值,这时候的存储过程如下所示:

  

                                                                                                                                   node[E].next=-1

                                                                                                                                            |

                                                                node[0]    node[1]     node[2]     node[3]........node[E]

                                                                                                                            |               |

                                                                                                                   head[3456]    head[h]

发生冲突时存储过程如下所示:

 

 

                                                                                              node[E].next=-1            node[E].next=2

                                                                                                         |                                   |

                                                                node[0]    node[1]     node[2]     node[3]........node[E]

                                                                                                                            |               |

                                                                                                                   head[3456]    head[h]

 

所以当我们进行查询时,先计算出键值h和标识数值a,b,x,得i=head[h],如果查询node[i]发现(node[i].x==x&&node[i].a==a&&node[i].b==b)的条件不成立,我们知道发生的冲突,接下来就好办了,令i=node[E].next,继续(node[i].x==x&&node[i].a==a&&node[i].b==b)的比对,直到符合条件。

从更一般的角度看其实数据的存储如下图:

 

                                                                 有冲突的数据      head[h]           无冲突的数据           head[q]

                                                                                                  |                                                       |

                                                                                             node[E]                                          node[x]

                                                                                                  |                                                       |

                                                                                            node[s] (s=node[E].next)             NULL(-1=node[x].next)

                                                                                        .......................

 

【3】效率问题除了一般的时间换空间的思路外,还有一个值得注意的就是输入输出上。

航空公司VIP客户查询【PAT】,布布扣,bubuko.com

航空公司VIP客户查询【PAT】

原文:http://blog.csdn.net/linsheng9731/article/details/22619583

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!