THU-OJ-"PA1-2"-"Zuma Issue"
来源:互联网 发布:mysql,书 编辑:程序博客网 时间:2024/05/17 09:31
题目描述
祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。
开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成。
游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。
输入
第一行是一个由大写字母’A’~’Z’组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。
第二行是一个数字n,表示整个回放过程共有n次操作。
接下来的n行依次对应于各次操作。每次操作由一个数字k和一个大写字母Σ描述,以空格分隔。其中,Σ为新珠子的颜色。若插入前共有m颗珠子,则k ∈ [0, m]表示新珠子嵌入之后(尚未发生消除之前)在轨道上的位序。
输出
输出共n行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上的珠子序列。
如果轨道上已没有珠子,则以“-”表示。
样例
见英文题面
限制
0 ≤ n ≤ 10^4
0 ≤ 初始珠子数量 ≤ 10^4
时间:2 sec
内存:256 MB
提示
列表
思考:
这道题在二分查找题目之后,根据教学顺序应该使用列表。而提示中也表示使用列表来做。因此考虑列表实现。
由于OJ上并没有库,因此只能够自己定义列表类。不过这样也很好,正好能够定制一些独特的功能,也有助于对列表的理解。
代码如下:
#include <stdio.h>#include <string.h>#include <cstring>#include <stdlib.h>#define Posi(T) ListNode<T>*#define Rank int#define PRE 1 //向前搜索#define AFT 2 //向后搜索using namespace std;template <typename T> struct ListNode{//标准节点类 T data; Posi(T) pred; Posi(T) succ; ListNode(){}; ListNode(T e,Posi(T) p=NULL,Posi(T) s=NULL):data(e),pred(p),succ(s){}; Posi(T) insertAsPred(T const& e){ Posi(T) x=new ListNode(e,pred,this); pred->succ=x; pred=x; return x; }; Posi(T) insertAsSucc(T const& e){ Posi(T) x=new ListNode(e,this,succ); succ->pred=x; succ=x; return x; };};//快速IOconst int SZ = 1 << 20; //提升IO buffstruct fastio{ char inbuf[SZ]; char outbuf[SZ]; fastio(){ setvbuf(stdin, inbuf, _IOFBF, SZ); setvbuf(stdout, outbuf, _IOFBF, SZ); }}io;template <typename T> class List{//列表类 private: int _size; Posi(T) header; Posi(T) trailer; public: void init(){ header =new ListNode<T>; trailer=new ListNode<T>; header->succ=trailer; header->pred=NULL; trailer->pred=header; trailer->succ=NULL; _size=0; } Posi(T) operator[](Rank r) const{//寻秩访问 Posi(T) p=header; while(-1<r--) p=p->succ; return p; } //获取头尾节点 Posi(T) HEADER()const{ return header; } Posi(T) TRAILER()const{ return trailer; } //输出列表内容 void out()const{ Posi(T) p=header; if(p->succ==trailer){ printf("-"); } else{ while((p=p->succ)!=trailer){ printf("%c",p->data); } } printf("\n"); } //直接连接某两个节点 void link(Posi(T) p1,Posi(T) p2){ p1->succ=p2; p2->pred=p1; }};void elim(Posi(char) p,List<char> e); //以节点p为中心,对e序列进行对消操作int main(){ //************************************************************ //Data Input char str[10001]; int times; gets(str); int length=strlen(str); List<char> zuma; zuma.init(); Posi(char) p=zuma.HEADER(); for(int i=0;i<length;i++){ Posi(char) e=p->insertAsSucc(str[i]); p=e; } scanf("%d",×); int* posi=new int[times+1]; char* word=new char[times+1]; for(int i=0;i<times;i++){ scanf("%d %s",&posi[i],&word[i]); } //************************************************************* //Process for(int i=0;i<times;i++){ Posi(char) insert=zuma[posi[i]-1]->insertAsSucc(word[i]); bool elim_flag=true; while(elim_flag){ insert=elim(insert,zuma); if(insert==zuma.TRAILER()){ elim_flag=false; } } zuma.out(); }}//前后同字符数量搜索int pre_elim(Posi(char) p,List<char> e){ int k=0; char t=p->data; while((p->pred!=e.HEADER())&&(p->pred->data==t)){ p=p->pred; k++; } return k;}int aft_elim(Posi(char) p,List<char> e){ int k=0; char t=p->data; while((p->succ!=e.TRAILER())&&(p->succ->data==t)){ p=p->succ; k++; } return k;}//连接字符Posi(char) dellink(Posi(char) p,List<char> e,int pre,int aft){ Posi(char) p1=p; Posi(char) p2=p; while(pre-->-1){ p1=p1->pred; } while(aft-->-1){ p2=p2->succ; } e.link(p1,p2); return p2;}//对消函数Posi(char) elim(Posi(char) p,List<char> e){ int pre,aft; pre=pre_elim(p,e); aft=aft_elim(p,e); if(pre+aft>=2){ return dellink(p,e,pre,aft); } else{ return e.TRAILER(); }}
以上即为利用列表解决zuma问题。在OJ上测例通过率为95%,情况如下图所示:
在编程中遇到并解决了下列问题:
空格字符输入问题
OJ测例3是空字符的输入。因为最初不了解getchar()、scanf()、gets()之间的区别,使用了scanf输入字符。以下是三者的区别
getchar(),可以读取空格回车在内的一个字符,常常用来处理上文输入时候缓冲区内的回车等,以确保下文可以正常接收
scanf(),接收一个字符串,以空格回车作为结束标识,如果输入字符串那么回车会变成’\0’被放在字符串结尾,如果是其他类型,回车会继续停留在缓冲区等待下个变量接受
gets(),接受一个长串,期中可以接受空格等,以回车符作为结束标志,但其也可以接受一个回车,产生一个空串.如果上句是scanf并且输入的是字符串,那么不会接收回车
快速IO
OJ上测试的数据量是非常大的,所以在设计程序时必须考虑时间复杂度。为了实现快速输入输出,需要调大流缓冲区。这也算是OJ题目必备的奇淫巧技吧。
FASTIO代码:
快速IO
const int SZ = 1<<20; struct fastio{ //fast io
char inbuf[SZ];
char outbuf[SZ];
fastio(){
setvbuf(stdin,inbuf,_IOFBF,SZ);
setvbuf(stdout,outbuf,_IOFBF,SZ);
解释:设置文件缓冲区函数
void setbuf(FILE *stream,char *buf);
void setvbuf(FILE *stream,char *buf,int type,unsigned size);
这两个函数将使得打开文件后,用户可建立自己的文件缓冲区,而不使用fopen()函数打开文件设定的默认缓冲区。
对于setbuf()函数,buf指出缓冲区长度,由stdio.h中定义的宏BUFSIZE的值决定,缺省为512字节。当buf为空时,setbuf函数将使的文件I/O不带缓冲。
对setvbuf函数,则由malloc函数来分配缓冲区,参数size指明了缓冲区的长度。
type则表示了缓冲的类型,其值可以取如下值:
_IOFBF 文件全部缓冲,即缓冲区装满后,才能对文件读写
_IOLBF 文件行缓冲,即缓冲区接收到一个换行符时,才能对文件读写
Runtime error(ExitCode 6)问题
Linux上Runtime error(ExitCode 6)错误,与动态内存的分配与销毁等有关。但是网上一直没有能够找到一个权威的解释。最初在测例17、19上出现该错误,并且久久无法解决。直到将代码中每一个数组进行debug,最后才锁定了问题:
Main函数中:
int* posi=new int[times+1]; char* word=new char[times+1]; for(int i=0;i<times;i++){ scanf("%d %s",&posi[i],&word[i]); }
尽管scanf只会用到posi[time-1],但是申请内存时却要申请int[time+1]大小的内存,否则就要报错。理论上来讲,这件事是说不通的。但是由于OJ不能gdb调试,看不见内存的情况,所以暂时也无法进一步细细讨论了~希望有大腿能够指教!
- THU-OJ-"PA1-2"-"Zuma Issue"
- Tsinghua OJ:祖玛(Zuma)
- THU数据结构编程作业一:祖玛(Zuma)
- 逆序对计算的思考 (Tsinghua OJ,PA1)
- 数据结构1-2Zuma
- Zuma
- Week 2 - Wed. & Thu.
- THU MAR 5,2009(2)
- Tsinghua OJ 数据结构编程作业:祖玛(Zuma)
- 机房练习赛hao 【Tsinghua OJ】祖玛(Zuma) (字符串)
- Codeforces Round #336 (Div. 2) D. Zuma
- Codeforces Round #336 (Div. 2) D. Zuma
- LTE issue 2
- issue
- issue
- issue
- Codeforces Round #336 (Div. 2) 608D Zuma(dfs+dp)
- Codeforces Round #336 (Div. 2) D. Zuma(区间dp)
- 你是去上大学,别让大学上了你
- 利用HTML和CSS实现常见的布局
- PHP面向对象_内置标准类,普通数据类型转为对象类型
- Node.js 回调函数来解决SQL语句与返回值的异步问题
- [LeetCode]--412. Fizz Buzz
- THU-OJ-"PA1-2"-"Zuma Issue"
- JS时钟
- 多线程继承Thread类
- info-detail-476094.html
- Python中元类的执行优先次序
- codeforces-731E-dp
- 多线程实现Runnable接口
- テクニカルアーティストについての記事をいくつか見つけました
- thinkPHP模糊查询语句like组合写法其中一种