Team Queue (佇列的一種應用)

haixinjiazu發表於2019-05-10

題目:Team Queue
Queues and Priority Queues are data structures which are known to most computer scientists. The Team Queue, however, is not so well known, though it occurs often in everyday life. At lunch time the queue in front of the Mensa is a team queue, for example.
In a team queue each element belongs to a team. If an element enters the queue, it first searches the queue from head to tail to check if some of its teammates (elements of the same team) are already in the queue. If yes, it enters the queue right behind them. If not, it enters the queue at the tail and becomes the new last element (bad luck). Dequeuing is done like in normal queues: elements are processed from head to tail in the order they appear in the team queue.
Your task is to write a program that simulates such a team queue.
Input
The input will contain one or more test cases. Each test case begins with the number of teams t (1<=t<=1000). Then t team descriptions follow, each one consisting of the number of elements belonging to the team and the elements themselves. Elements are integers in the range 0 – 999999. A team may consist of up to 1000 elements.
Finally, a list of commands follows. There are three different kinds of commands:
ENQUEUE x – enter element x into the team queue
DEQUEUE – process the first element and remove it from the queue
STOP – end of test case
The input will be terminated by a value of 0 for t.
Output
For each test case, first print a line saying “Scenario #k”, where k is the number of the test case. Then, for each DEQUEUE command, print the element which is dequeued on a single line. Print a blank line after each test case, even after the last one.

樣例:
Sample Input
2
3 101 102 103
3 201 202 203
ENQUEUE 101
ENQUEUE 201
ENQUEUE 102
ENQUEUE 202
ENQUEUE 103
ENQUEUE 203
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
2
5 259001 259002 259003 259004 259005
6 260001 260002 260003 260004 260005 260006
ENQUEUE 259001
ENQUEUE 260001
ENQUEUE 259002
ENQUEUE 259003
ENQUEUE 259004
ENQUEUE 259005
DEQUEUE
DEQUEUE
ENQUEUE 260002
ENQUEUE 260003
DEQUEUE
DEQUEUE
DEQUEUE
DEQUEUE
STOP
0

Sample Output
Scenario #1
101
102
103
201
202
203

Scenario #2
259001
259002
259003
259004
259005
260001

題目大意:就是先輸入t行,表示t個小隊,其中的數值就是這個小隊的隊員。然後之後再專門組成一個大佇列,這個大佇列和小隊之間沒有關係的,但是在依次排隊的時候,如果這個正準備排隊的成員在之前有隊友在前面,則排到隊友的那一群的後面,如果沒有隊友則要排到大佇列的隊尾。

思路:找一個陣列還記錄這個小隊是否在大隊裡,且在大佇列用一個二維陣列存,其中每一行的首元素表示為這一行是哪個小隊的,之後根據這個正要進入大佇列的成員確定其所在小隊是否已經在大佇列中,如果在則放到這個小隊的那一行的最後,如果不在則在大佇列中的最後表示這個新的小隊的存在,然後再這一個小隊的這一行的第一個元素為這個成員。然後在出隊伍的時候,依次從大佇列的第一個小隊的第一個成員出,因為這題非常容易超時,所以把千萬避免遍歷,所以要把大佇列的隊首記下來,大佇列的隊尾記錄下來,每個小隊的第一個元素記下來,每個小隊的個數記下來。還是因為時間問題,這題千萬不能移動元素,因為這樣非常耗時,所以要改變的是記錄大佇列隊首和大佇列隊尾的數值,還有改變小隊的隊首與每個小隊的個數;(也是因為這個原因,沒辦法用連結串列進行,只能用陣列進行);

新技巧:對於這種查詢耗時很長的佇列問題,用連結串列就相對麻煩很多了,所以這時候就考慮用陣列就可以,而且這題還出現了範圍,所以用陣列可以。(這題如果要改成連結串列就要把每個小隊作為一個佇列然後進行隊尾插入,隊首刪除),不過因為這樣會非常的麻煩,因為要為每個存在於大佇列的小隊建立一個連結串列。所以不如用陣列方便些(陣列會出現記憶體的問題,這個也要注意)。(所以對於資料結構的問題的處理,用連結串列和陣列理論上都可以,但有簡單和方便,還有時間問題的區別,具體選擇哪個具體分析)(但記住,陣列查詢方便,插入到中間不方便,刪除也不方便(這題不是直接刪除),佇列問題的陣列插入還是比較簡單。連結串列查詢麻煩,因為有很大的可能性需要遍歷,但是插入的時候簡單,只需要改變節點的指向即可,刪除也簡單,尤其是對於佇列的連結串列處理,只用改變頭節點指向和尾節點指向即可。);

自己的建議:對於資料結構的問題,最好一上來先考慮用連結串列來進行,畢竟動態分配要靈活的多。當用連結串列實在麻煩,不方便,或者說超時的問題的時候,再去考慮用陣列。

程式碼:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int number[1005];
int s_mumber[1000005];
int s_num[5005][1005];

int main()
{
    int t,j,i,num=0,n,ttt,start;
    char ss[10];
    while(scanf("%d",&t)!=EOF&&t!=0)
    {
        for(i=0;i<t;i++)
        {
            scanf("%d",&n);
            for(j=0;j<n;j++)
            {
                scanf("%d",&ttt);
                number[j]=0;
                s_mumber[ttt]=i;
            }
        }
        int times=0;
        num++;start=0;
        printf("Scenario #%d
",num);
        while(1)
        {
            scanf("%s",ss);
            if(ss[0]==`E`)
            {
                scanf("%d",&ttt);
                i=s_mumber[ttt];
                if(number[i]==0)
                {
                    s_num[times][0]=i;
                    s_num[times][1]=1;
                    s_num[times][2]=3;
                    s_num[times][3]=ttt;
                    number[i]=1;
                    times++;
                }
                else
                {
                    for(j=start;j<times;j++)
                        if(i==s_num[j][0])
                            break;
                    s_num[j][1]++;
                    s_num[j][s_num[j][2]+s_num[j][1]-1]=ttt;
                }
            }
            else if(ss[0]==`S`)
                break;
            else if(ss[0]==`D`)
            {
                if(s_num[start][1]==0)
                {
                    number[s_num[start][0]]=0;
                    start++;
                    printf("%d
",s_num[start][s_num[start][2]]);
                    s_num[start][2]++;
                    s_num[start][1]--;
                }
                else
                {
                    printf("%d
",s_num[start][s_num[start][2]]);
                    s_num[start][2]++;s_num[start][1]--;
                }
            }
        }
        printf("
");
    }
    return 0;
}

相關文章