zoukankan      html  css  js  c++  java
  • PTA 11-散列4 Hard Version (30分)

    题目地址

    https://pta.patest.cn/pta/test/16/exam/4/question/680

    5-18 Hashing - Hard Version   (30分)

    Given a hash table of size NN, we can define a hash function . Suppose that the linear probing is used to solve collisions, we can easily obtain the status of the hash table with a given sequence of input numbers.

    However, now you are asked to solve the reversed problem: reconstruct the input sequence from the given status of the hash table. Whenever there are multiple choices, the smallest number is always taken.

    Input Specification:

    Each input file contains one test case. For each test case, the first line contains a positive integer NN (le 10001000), which is the size of the hash table. The next line contains NN integers, separated by a space. A negative integer represents an empty cell in the hash table. It is guaranteed that all the non-negative integers are distinct in the table.

    Output Specification:

    For each test case, print a line that contains the input sequence, with the numbers separated by a space. Notice that there must be no extra space at the end of each line.

    Sample Input:

    11
    33 1 13 12 34 38 27 22 32 -1 21
    

    Sample Output:

    1 13 12 21 33 34 38 27 22 32


    根据hash表算原始的插入顺序,很有意思的题,mooc讲了思路。
    /*
    评测结果
    时间	结果	得分	题目	编译器	用时(ms)	内存(MB)	用户
    2017-07-08 11:46	答案正确	30	5-18	gcc	6	4	
    测试点结果
    测试点	结果	得分/满分	用时(ms)	内存(MB)
    测试点1	答案正确	18/18	2	1
    测试点2	答案正确	4/4	2	1
    测试点3	答案正确	2/2	2	1
    测试点4	答案正确	2/2	2	1
    测试点5	答案正确	4/4	6	4
    
    刚开始找应该输出的点时,暴力扫描取最小,结果发现第三个点超时
    后来改用堆找最小结点
    发现还是超时。。。
    然后没辙了,找了个带注释的测试点截图,第三个点写到,有非-1的空位
    
    WTF!
    
    改了之后发现这个数据量,用暴力扫最小结点耗时也是十几毫秒,没慢多少,但是按理说还是用堆比较科学。
    ————————————————
    读入hash表-> 表里i位置上的元素,如果算完hash应该插在j位置上,那么从i-1,一直减到j,这些元素都要在i之前插入。
    用(i-1+N)%N解决hash表的循环问题
    
    把依赖关系计算完后,此时问题就成了拓扑排序。
    再接下来就是怎么找入度为0的结点中,包含元素最小的点了。
    此解法建了堆,最开始把入度为0的全部提前压进去,然后开始循环往外取。
    取出后断开该结点发出的边与其它点的连接。如果断开后发现其它结点入度变成了0,那么立即把该入度为0的点扔到堆里。
    */
    #include<stdio.h>
    #define TRUE 1
    #define FALSE 0
    #define MAXN 1000
    #define EMPTY -1
    #define INFINITY 6666666
    
    struct HashNode
    {
    	int value;
    	int visited; //是否访问过
    	int noCollision; //是否有冲突,建矩阵的时候用
    	int indegree; //入度
    } gHashTable[MAXN];
    
    int gMatrix[MAXN][MAXN];
    int Heap[MAXN+1]; //堆
    int HeapLength=0; //堆长
    
    void DBG_printHeap() //debug时打印堆的
    {
    	int i;
    	for(i=1;i<=HeapLength;i++)
    	{
    		printf("%d ",gHashTable[Heap[i]].value);
    	}
    	printf("+++++
    ");
    }
    void InsertIntoHeap(int a) //插入堆
    {
    	int i;
    	Heap[++HeapLength]=a;
    	i=HeapLength;
    	while(i/2>0)
    	{
    		if(gHashTable[Heap[i/2]].value>gHashTable[a].value)
    		{
    			Heap[i]=Heap[i/2];
    			i=i/2;
    		}
    		else break;
    	}
    	Heap[i]=a;
    //	DBG_printHeap();
    }
    
    int DeHeap() //弹出堆顶
    {
    	if(HeapLength==0)
    		return EMPTY;
    	int top=Heap[1];
    	int temp,parent,child;
    	Heap[1]=Heap[HeapLength--];
    	temp=Heap[1];
    	for(parent=1;2*parent<=HeapLength;parent=child)
    	{
    		child=parent*2;
    		if(child!=HeapLength)
    		{
    			if(gHashTable[Heap[child]].value>gHashTable[Heap[child+1]].value)
    			child++;
    		} 
    		
    		if(gHashTable[temp].value>gHashTable[Heap[child]].value)
    			Heap[parent]=Heap[child];
    		else break;
    	}
    	Heap[parent]=temp;
    //	DBG_printHeap();
    	return top;
    }
    
    
    void CalcMatrix(int N) //计算依赖关系的邻接矩阵
    {
    	int i,idx,p;
    	for(i=0;i<N;i++)
    	{
    		if(gHashTable[i].noCollision==1 || gHashTable[i].value==EMPTY)
    			continue;
    		idx=gHashTable[i].value%N;
    		p=(i-1+N)%N;
    		while(p!=idx)
    		{
    			if(gHashTable[p].value!=EMPTY)
    			gMatrix[p][i]=TRUE;
    			gHashTable[i].indegree++;
    			p=(p-1+N)%N;
    		}
     	 	gMatrix[idx][i]=TRUE;
    		gHashTable[i].indegree++;
    	}
    }
    
    void DeleteEdges(int idx,int N) //删边
    {
    	int i;
    	for(i=0;i<N;i++)
    	{
    		if(gMatrix[idx][i])
    		{
    //			gMatrix[idx][i]=FALSE;
    			gHashTable[i].indegree--;
    			if(gHashTable[i].indegree==0)
    			{
    //				gHashTable[i].visited=TRUE;
    				InsertIntoHeap(i);
    			}
    		}
    	}
    //	gHashTable[idx].visited=TRUE;
    }
    
    int InitHeapBeforePop(int N) //最开始时扫描结点,把入度为零的扔堆里面
    {
    	int i;
    
    	for(i=0;i<N;i++)
    	{
    		if(gHashTable[i].visited==TRUE || gHashTable[i].indegree!=0)
    			continue;
    		else
    			InsertIntoHeap(i);
    	}
    }
    
    int main()
    {
    	int N,i,temp,firstprint;
    	scanf("%d",&N);
    	for(i=0;i<N;i++)
    	{
    		scanf("%d",&gHashTable[i].value);
    		if(gHashTable[i].value%N==i)
    			gHashTable[i].noCollision=TRUE;// 下标和hash值相符,说明没冲突
    		if(gHashTable[i].value<0)
    			gHashTable[i].value=EMPTY;  //标识空位
    		if(gHashTable[i].value==EMPTY)
    			gHashTable[i].visited=TRUE; //把空位的visited置1,后续不处理
    	}
    	CalcMatrix(N);
    	InitHeapBeforePop(N);
    	firstprint=1; //处理格式问题,第一个字符前面不加空格
    	while((temp=DeHeap()) != EMPTY)
    	{
    		DeleteEdges(temp,N);
    		if(!firstprint)
    			putchar(' ');
    		printf("%d",gHashTable[temp].value);
    		firstprint=0;
    	}
    }
    

      

  • 相关阅读:
    HDOJ 1677 Nested Dolls(LIS+Dilworth)
    POJ 1548 Robots (Dilworth)
    POJ 1065 Wooden Sticks
    第三百四十天 how can I 坚持
    第三百三十九天 how can I 坚持
    第三百三十八天 how can I 坚持
    第三百三十七天 how can I 坚持
    第三百三十六天 how can I 坚持
    第三百三十五天 how can I 坚持
    第三百三十四天 how can I 坚持
  • 原文地址:https://www.cnblogs.com/gk2017/p/7141192.html
Copyright © 2011-2022 走看看