1、又是一道让我永生难忘的题。。。交了21次才过,创纪录了。
2、题目给出一些数,每个数属于不同的组,然后给出一串命令,1、入队:看看整个队伍里有没有和自己同组的,如果有,“插队”到同组的人的末尾,形成一个“小团体”;如果没有,直接排到队伍的末尾。2、出队:队伍第一个元素出队。3、结束:换下一组数据。
3、看似简单,实际上写起来并不容易,尤其是用C语言(伪C++)。刚开始想用二维数组水过,每个一维数组是一个“小团体”,但是由于数组是静态的,打个比方,第一团体被清空了,那么下一次第一团体的人就要到整个队伍的末尾了,这样数组需要变长,但是长到什么程度不知道,因为命令有200000行,数组可能装不下,所以只好放弃。
4、无奈之下只能用链表了。事实证明每次想用数组蒙混过关都没有好下场。这是我第一次写用指针实现的链表,自然是RE一堆,原因是访问非法内存,比如说读到了NULL还以为是读到了结点,进行对结点的操作,自然会RE。
5、每一个“小团体”都要有一个头指针和尾指针,整个队列也要有一个头指针和尾指针,要有一个数组group标记一个元素属于哪个小组,要有数组have标记还有多少数字没用过,防止出现无效命令(比如插入数字num但是num已经全部进队伍里了),用in_list标记队伍中有没有和自己同组的,以省去查找时间,用list表示队伍中有几个同组的,若为0的话,则in_list也要改变。
6、插入结点的时候要考虑各种特殊情况,比如队伍中一个结点都没有,或者已经有结点了但没有自己同组的,或者有结点且有自己同组的,注意每一次插入结点后,list_front,list_rear,front【】,rear【】是否改变都要考虑到。
7、出队列的时候也不那么简单,我就是栽在这里,以为出队列的时候还读入了num,实际上操作的应该是list_front,这就是典型的逻辑错误,很难找出。
8、所幸终于过了,对链表也有了深刻的理解,且不说能力提高了没有,失败的经验肯定是积累一大堆了(笑)。
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int a[1010][1010];
int group[1000010],have[1000010],in_list[1010],list[1010];
int count=0,t,n;
typedef struct Tnode
{
int v;
struct Tnode*left,*right;
}Node;
Node* newnode(void)
{
Node*u=(Node*)malloc(sizeof(Node));
if(u!=NULL)
{
u->v=-1;
u->left=NULL;
u->right=NULL;
}
return u;
}
void init(void)
{
int i,j;
memset(a,0,sizeof(a));
memset(group,0,sizeof(group));
memset(in_list,0,sizeof(in_list));
memset(list,0,sizeof(list));
memset(have,0,sizeof(have));
count++;
printf("Scenario #%d\n",count);
for(i=1;i<=t;i++)
{
scanf("%d",&n);
for(j=1;j<=n;j++)
{
scanf("%d",&a[i][j]);
a[i][0]++;
group[a[i][j]]=i;
have[a[i][j]]++;
}
}
}
int main(void)
{
//freopen("a.txt","r",stdin);
int num;
char s[50];
bool yes;
Node*front[1010],*rear[1010],*list_front,*list_rear,*u,*temp;
while(scanf("%d",&t)==1)
{
if(t==0)break;
init();
memset(s,'\0',sizeof(s));
yes=true;
while(fgets(s,50,stdin)!=NULL)
{
if(yes)
{
list_front=NULL;
list_rear=NULL;
memset(front,NULL,sizeof(front));
memset(rear,NULL,sizeof(rear));
yes=false;
}
if(s[0]=='E')
{
sscanf(s+7,"%d",&num);
u=newnode();u->v=num;
if(have[num])
{
if(list_front==NULL&&list_rear==NULL)
{
list_front=u;list_rear=u;in_list[group[num]]=1;
front[group[num]]=u;rear[group[num]]=u;
}
else
{
if(in_list[group[num]])
{
if((rear[group[num]]->right)!=NULL)
{
rear[group[num]]->right->left=u;
u->right=rear[group[num]]->right;
}
rear[group[num]]->right=u;
u->left=rear[group[num]];
}
else
{
list_rear->right=u;
u->left=list_rear;
list_rear=u;
in_list[group[num]]=1;
front[group[num]]=u;
}
if(list_rear==rear[group[num]]) list_rear=u;
rear[group[num]]=u;
}
list[group[num]]++;have[num]--;
}
}
if(s[0]=='D')
{
if(list_front==NULL) continue;
temp=list_front->right;
printf("%d\n",list_front->v);
list[group[list_front->v]]--;have[list_front->v]++;
if(list[group[list_front->v]]==0)
{
front[group[list_front->v]]=NULL;
rear[group[list_front->v]]=NULL;
in_list[group[list_front->v]]=0;
}
if(temp!=NULL)
{
list_front=temp;
}
else
{
list_front=NULL;
list_rear=NULL;
}
}
if(s[0]=='S')
{
memset(s,'\0',sizeof(s));
break;
}
memset(s,'\0',sizeof(s));
}
printf("\n");
}
return 0;
}