洛谷Oj-队列安排-模拟双向链表
来源:互联网 发布:java 线程池 获取队列 编辑:程序博客网 时间:2024/05/22 05:26
问题描述:
一个学校里老师要将班上N个同学排成一列,同学被编号为1~N,他采取如下的方法:
1.先将1号同学安排进队列,这时队列中只有他一个人;
2.2~N号同学依次入列,编号为i的同学入列方式为:老师指定编号为i的同学站在编号为1~i -1中某位同学(即之前已经入列的同学)的左边或右边;
3.从队列中去掉M(M
int mark[100001];int main(){ list<int>a;//双向链表a int n,m,i,k,p,t; list<int>::iterator it;//相当于指针的迭代器it scanf("%d",&n);//输入n a.push_back(1);//将编号为1的同学加入链表 for(i=2;i<=n;i++)//依次将编号为2到n的同学加入链表 { scanf("%d%d",&k,&p); it=find(a.begin(),a.end(),k);//在链表中查找编号为k的同学 if(p==1)//如果p为0,直接加入;p为1,则需要将it自增。注意it只能自增自减,不能加减一个常数 it++; a.insert(it,i);//加入 } scanf("%d",&m);//输入m for(i=1;i<=m;i++) { scanf("%d",&t);//输入要去掉的同学的编号 if(mark[t])//如果编号为t的同学已经被去掉过 continue; it=find(a.begin(),a.end(),t);//在链表中查找编号为t的同学 if(it!=a.end())//如果找到了。其实此语句对本题来说是多余的,因为一定能找到 a.erase(it);//删除迭代器位置上的元素 mark[t]=1;//将t标记 } for(it=a.begin();it!=a.end();it++)//遍历链表 printf("%d ",*it);//打印 printf("\n"); return 0; }
代码②(用指针实现双向链表+记忆化 超时):
struct node{ int data;//同学的编号 node *prev,*next;//每个的名称前都要有‘*’};node *nil,*a;//nil为指向头结点的指针node *dp[100001];//记忆化数组int mark[100001];//标记数组void init()//链表初始化{ nil=(node*)malloc(sizeof(node)); nil->next=nil; nil->prev=nil;}void insert(node* pros,int data)//将数据data插入链表中指针pors指向的节点的右侧{ node *x=(node *)malloc(sizeof(node)); x->data=data; x->next=pros->next;//以下为插入的四个步骤,难以用少量文字说明,请在纸上模拟这个过程 pros->next->prev=x; pros->next=x; x->prev=pros;}node* search(int key)//在链表中查找值为key的节点{ if(dp[key]!=NULL)//如果被记录过,直接返回 return dp[key]; node *cur=nil->next;//从头节点开始查找 while(cur!=nil&&cur->data!=key)//如果链表遍历完毕或节点被成功找到,就跳出循环 cur=cur->next; return dp[key]=cur;//返回并记忆化}void deletenode(node *t)//链表节点的删除{ if(t==nil)//如果是头节点,不对其进行删除操作 return; t->prev->next=t->next;//以下为删除的两个步骤,请在纸上模拟这个过程 t->next->prev=t->prev; free(t);//释放内存空间}int main(){ init();//初始化,以下代码与代码①思路相同 int n,m,i,k,p,t; scanf("%d",&n); insert(nil,1); for(i=2;i<=n;i++) { scanf("%d%d",&k,&p); a=search(k); if(p==0) a=a->prev; insert(a,i); } scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d",&t); if(mark[t]) continue; a=search(t); deletenode(a); mark[t]=1; } for(a=nil->next;a!=nil;a=a->next) printf("%d ",a->data); printf("\n"); return 0; }
AC代码③(用数组模拟双向链表):
struct node{ int prev; int next;};node list1[100001];//结构体数组list1int mark[100001];//标记数组int main(){ int n,m,i,j,k,p,t,cnt=0;//cnt记录被去掉的同学的人数 scanf("%d",&n); list1[0].next=1;//将编号为1的同学加入链表 for(i=2;i<=n;i++) { scanf("%d%d",&k,&p); if(p==0)//将编号为i的同学加入到编号为k的同学的左边 { list1[i].next=k;//注意以下四个步骤不是任意顺序的,上一行代码可能会影响到下一行代码 list1[i].prev=list1[k].prev; list1[list1[k].prev].next=i; list1[k].prev=i; } else//将编号为i的同学加入到编号为k的同学的右边 { list1[i].next=list1[k].next; list1[i].prev=k; list1[list1[k].next].prev=i; list1[k].next=i; } } scanf("%d",&m); for(i=1;i<=m;i++) { scanf("%d",&t); if(mark[t]) continue; list1[list1[t].prev].next=list1[t].next;//删除节点 list1[list1[t].next].prev=list1[t].prev; mark[t]=1;//标记 cnt++;//计数 } int cur; for(i=1;i<=n-cnt;i++)//循环次数为n-cnt { cur=list1[0].next;//从头节点指向的节点开始遍历链表 printf("%d ",cur);//打印 } printf("\n"); return 0; }
算法描述:
此题不可以用单向链表实现。果然还是数组比较快。通过这道题,虽然WA了十几次很闹心,但是我练习到了STL、指针链表、数组链表。这个收获还是蛮丰富的。
阅读全文
0 0
- 洛谷Oj-队列安排-模拟双向链表
- 数组模拟链表之P1160 队列安排
- 洛谷P1160 队列安排(模拟)
- SDUT OJ 1466 双向队列
- SDUT OJ 双向链表
- 玲珑OJ 1045 - I. Quailty and LRU Algorithm 模拟双向链表
- 【洛谷 1160】 队列安排
- 洛谷1160 队列安排
- 洛谷 P1160 队列安排
- 洛谷 P1160 队列安排
- 洛谷p1160队列安排
- 双向链表 + 栈 + 队列
- 双向链表实现队列
- 苏州OJ c004: 模拟队列
- 运动会安排(链队列)
- Basic Data Structurek(模拟,双向队列)
- UVA210 concurrency simulator (双向队列 & 模拟)
- Java双向队列,用双向链表实现的
- 查找方法总结---待完善
- 解决:mybatis执行SQL语句部分参数返回NULL
- js--排序算法
- Git-2017-06-11 20:17:19
- 项目的搭建环境1
- 洛谷Oj-队列安排-模拟双向链表
- 数据结构 哈希表的原理和代码实现
- 输入输出流对象
- 将虚拟机的ip改成固定的ip地址
- php程序员的技术成长规划
- 软件常用安全防护手段 checksec 总结
- 面向对象----->>原型重写扩充
- Android_RecyclerView实现上下滚动广告条(带图片)
- 23种设计模式(2):工厂模式(Factory Pattern)