第二次上机赛解题报告及标程

来源:互联网 发布:p2p网络借贷入罪 编辑:程序博客网 时间:2024/06/10 13:06

  此次上机,起码从board上看要比第一次好了许多……虽然距离理想状态还是差了一些……

  渣诚写的验题标程都是非STL的,有时间我会放上来……现在的标程STL居多先凑合看下= =

  A. Payment

  有点后悔把这道题放在第一道,以至于这道唯一和数据结构无关的题目让大多数人煎熬了好久……Codeforces Round #232 (Div. 2) B题改了下题目描述罢了,连数据都是直接从那里拖来的。做法上机时讲过了,不多说。我的代码里用的都是除法,所以只需要int,有些人的代码需要乘法操作,极端数据下会爆int,需要用long long。

#include<cstdio>using namespace std;int main(){    int n,l,r;    while(~scanf("%d%d%d",&n,&l,&r))        puts(n/l>(n-1)/r?"Yes":"No");}

  B. 婚礼车队

  不说数据结构是因为实在太明显了,可不是因为用不到……这道题的停车场是个典型的栈。每次判断栈顶是否符合所需编号,如果符合则出栈,否则将下一个元素进栈,依此类推。如果所有元素都已判断过且栈空则符合要求。由于自己太懒了直接扔个STL的,领会一下思想就好。

#include<cstdio>#include<algorithm>#include<stack>using namespace std;int main(){    int n,tmp;    stack<int> data,st;    while(~scanf("%d",&n))    {        for(int i=0; i<n; ++i)        {            scanf("%d",&tmp);            data.push(tmp);        }        bool flag=true;        for(int i=n; flag&&i>=1; --i)        {            if(!st.empty()&&st.top()==i)            {                st.pop();                continue;            }            while(!data.empty())            {                st.push(data.top());                data.pop();                if(st.top()==i)                    break;            }            if(st.top()!=i)                flag=false;            else                st.pop();        }        puts(flag?"Yes":"No");        while(!data.empty())            data.pop();        while(!st.empty())            st.pop();    }}

  C. TXT Editer

  陈题,一开始就认为这道题很好,一直留到上机。一方面可以用双链表来做,简单的移动插入删除。另外还可以用栈来做,拿两个栈,栈口相对,相接处就是光标。光标向左移动就是左栈元素弹出进右栈,反之亦然;插入删除都是对左栈进行的操作。非常巧妙。膜拜下提出此做法的昂神Orz……

  先是链表版的,用STL因为我懒= =

//using list#include<cstdio>#include<cstring>#include<list>using namespace std;const int MAXN=500005;list<char> data;list<char>::iterator it;char op[MAXN];int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%s",op);        int l=strlen(op);        it=data.end();        for(int i=0; i<l; ++i)            switch(op[i])            {            case 'L':                if(it!=data.begin())                    --it;                break;            case 'R':                if(it!=data.end())                    ++it;                break;            case 'B':                if(it!=data.begin())                    it=data.erase(--it);                break;            default:                data.insert(it,op[i]);            }        for(it=data.begin(); it!=data.end(); ++it)            putchar(*it);        putchar('\n');        data.clear();    }}

  然后是用栈做的。

//using stack#include<cstdio>#include<cstring>#include<stack>using namespace std;const int MAXN=500005;stack<char> p,q;char op[MAXN];int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%s",op);        int l=strlen(op);        for(int i=0; i<l; ++i)            switch(op[i])            {            case 'L':                if(!p.empty())                {                    q.push(p.top());                    p.pop();                }                break;            case 'R':                if(!q.empty())                {                    p.push(q.top());                    q.pop();                }                break;            case 'B':                if(!p.empty())                    p.pop();                break;            default:                p.push(op[i]);            }        while(!p.empty())        {            q.push(p.top());            p.pop();        }        while(!q.empty())        {            putchar(q.top());            q.pop();        }        putchar('\n');    }}

  我们注意到用栈做时,最后输出时为保证正序,需要将左栈元素全部弹入右栈,相当于光标移到最左侧,然后再从右栈中依次弹出并输出。太麻烦了,所以把左栈改成双端队列,嗯对还是STL。

//using deque+stack#include<cstdio>#include<cstring>#include<deque>#include<stack>using namespace std;const int MAXN=500005;deque<char> p;stack<char> q;char op[MAXN];int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%s",op);        int l=strlen(op);        for(int i=0; i<l; ++i)            switch(op[i])            {            case 'L':                if(!p.empty())                {                    q.push(p.back());                    p.pop_back();                }                break;            case 'R':                if(!q.empty())                {                    p.push_back(q.top());                    q.pop();                }                break;            case 'B':                if(!p.empty())                    p.pop_back();                break;            default:                p.push_back(op[i]);            }        while(!p.empty())        {            putchar(p.front());            p.pop_front();        }        while(!q.empty())        {            putchar(q.top());            q.pop();        }        putchar('\n');    }}

  D. 表达式计算

  陈题,书上有几乎所有的代码。我们严重怀疑当年的出题人在出数据的时候,代码里使用的是书上的float,所以这道题把float改成double的会WA……嗯对数据里有精度问题,我们一开始也没想到,说声sorry。其他的不多讲了。

#include<cstdio>using namespace std;const struct{    char ch;    int pri;} lpri[7]= {{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},  rpri[7]= {{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};int leftpri(char op){    for(int i=0; i<7; i++)        if(lpri[i].ch==op)            return lpri[i].pri;}int rightpri(char op){    for(int i=0; i<7; i++)        if(rpri[i].ch==op)            return rpri[i].pri;}bool InOp(char ch){    return ch=='('||ch==')'||ch=='+'||ch=='-'||ch=='*'||ch=='/';}int Precede(char op1,char op2){    if(leftpri(op1)==rightpri(op2))        return 0;    if(leftpri(op1)<rightpri(op2))        return -1;    return 1;}void trans(char *exp,char postexp[]){    struct    {        char data[100];        int top;    } op;    int i=0;    op.top=0;    op.data[op.top]='=';    while(*exp!='\0')    {        if(!InOp(*exp))        {            while(*exp>='0'&&*exp<='9')                postexp[i++]=*(exp++);            postexp[i++]='#';        }        else            switch(Precede(op.data[op.top],*exp))            {            case -1:                op.data[++op.top]=*(exp++);                break;            case 0:                --op.top;                ++exp;                break;            case 1:                postexp[i++]=op.data[op.top--];                break;            }    }    while(op.data[op.top]!='=')        postexp[i++]=op.data[op.top--];    postexp[i]='\0';}int compvalue(char *postexp){    struct    {        float data[100];        int top;    } st;    float d,a,b,c;    st.top=-1;    while(*postexp!='\0')    {        switch(*postexp)        {        case '+':            a=st.data[st.top--];            b=st.data[st.top--];            c=a+b;            st.data[++st.top]=c;            break;        case '-':            a=st.data[st.top--];            b=st.data[st.top--];            c=b-a;            st.data[++st.top]=c;            break;        case '*':            a=st.data[st.top--];            b=st.data[st.top--];            c=a*b;            st.data[++st.top]=c;            break;        case '/':            a=st.data[st.top--];            b=st.data[st.top--];            c=b/a;            st.data[++st.top]=c;            break;        default:            d=0;            while(*postexp>='0'&&*postexp<='9')                d=d*10+*(postexp++)-'0';            st.data[++st.top]=d;            break;        }        ++postexp;    }    return st.data[st.top];}int main(){    int t;    scanf("%d",&t);    while(t--)    {        char exp[100],postexp[100];        scanf("%s",exp);        trans(exp,postexp);        printf("%s\n%d\n",postexp,compvalue(postexp));    }}

  E. Arthur爱打羽毛球

  裸得不能再裸的队列。只要注意取出特定羽毛球的过程中,队头弹出编号,不是所要的,就再弹进队尾,直到找到特定编号或者转了一个圈就结束。

#include<cstdio>#include<queue>using namespace std;int main(){    int n,m,k;    char op[10];    queue<int> q;    while(~scanf("%d%d",&n,&m))    {        while(m--)        {            scanf("%s",op);            switch(op[0])            {            case 'P':                scanf("%d",&k);                if(q.size()<n)                    puts("JUSTME");                else                {                    q.pop();                    puts("OOPS");                }                q.push(k);                break;            case 'S':                scanf("%d",&k);                for(int i=0; i<q.size(); ++i)                {                    if(q.front()==k)                        break;                    q.push(q.front());                    q.pop();                }                if(q.front()==k)                {                    puts("GOTIT");                    q.pop();                }                else                    puts("WHERE");                break;            case 'R':                if(q.empty())                    puts("NONE");                else                {                    printf("%d\n",q.front());                    q.pop();                }                break;            }        }        while(!q.empty())            q.pop();    }}

  F. 括号匹配

  书上例题的加强版。一种括号变成三种罢了,左括号进栈,右括号判断是否和栈顶匹配,很简单。放两个版本的标程。

#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;struct SqStack{    char data[105];    int top;};void InitStack(SqStack *&s){    s=(SqStack *)malloc(sizeof(SqStack));    s->top=-1;}void Push(SqStack *&s,char e){    s->data[++s->top]=e;}void Pop(SqStack *&s,char &e){    e=s->data[s->top--];}bool GetTop(SqStack *&s,char &e){    if(s->top==-1)        return false;    e=s->data[s->top];    return true;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        char str[105],e;        scanf("%s",str);        bool match=true;        SqStack *s;        InitStack(s);        int l=strlen(str);        for(int i=0; match&&i<l; ++i)            switch(str[i])            {            case '(':            case '[':            case '{':                Push(s,str[i]);                break;            case ')':            case ']':            case '}':                if(GetTop(s,e)&&((e=='('&&str[i]==')')||(e=='['&&str[i]==']')||(e=='{'&&str[i]=='}')))                    Pop(s,e);                else                    match=false;                break;            }        if(s->top!=-1)            match=false;        free(s);        puts(match?"Yes":"No");    }}
#include<cstdio>#include<cstring>#include<stack>using namespace std;int main(){    int t;    char str[100];    stack<char> s;    scanf("%d",&t);    while(t--)    {        scanf("%s",str);        bool match=true;        int l=strlen(str);        for(int i=0; match&&i<l; ++i)            switch(str[i])            {            case '(':            case '[':            case '{':                s.push(str[i]);                break;            case ')':            case ']':            case '}':                if(!s.empty()&&((s.top()=='('&&str[i]==')')||(s.top()=='['&&str[i]==']')||(s.top()=='{'&&str[i]=='}')))                    s.pop();                else                    match=false;                break;            }        if(!s.empty())            match=false;        puts(match?"Yes":"No");        while(!s.empty())            s.pop();    }}

  G. 天马's wish

  陈题,和F题无本质区别。注意Holmes虽然“通杀”但只是女性通杀,不是男女通杀……题干里已经说了他是男性Orz,给你们的想象力跪了……

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<cctype>using namespace std;const int MAXN=100005;struct SqStack{    char data[MAXN];    int top;};void InitStack(SqStack *&s){    s=(SqStack *)malloc(sizeof(SqStack));    s->top=-1;}void Push(SqStack *&s,char e){    s->data[++s->top]=e;}void Pop(SqStack *&s,char &e){    e=s->data[s->top--];}bool GetTop(SqStack *&s,char &e){    if(s->top==-1)        return false;    e=s->data[s->top];    return true;}int main(){    char str[MAXN],e;    while(~scanf("%s",str))    {        int l=strlen(str)-2;        SqStack *t;        InitStack(t);        for(int i=1; i<=l; i++)            if(GetTop(t,e))            {                if((str[i]!='%'&&e!='%')&&abs(e-str[i])=='a'-'A')                    Pop(t,e);                else if(str[i]=='%'&&islower(e))                    Pop(t,e);                else if(e=='%'&&islower(str[i]))                    Pop(t,e);                else                    Push(t,str[i]);            }            else                Push(t,str[i]);        puts(t->top==-1?"Yes":"No");    }}
#include<cstdio>#include<cstring>#include<cmath>#include<cctype>#include<stack>using namespace std;const int MAXN=100005;int main(){    char str[MAXN];    stack<char> s;    while(~scanf("%s",str))    {        int l=strlen(str)-2;        for(int i=1; i<=l; i++)            if(!s.empty())            {                if((str[i]!='%'&&s.top()!='%')&&abs(s.top()-str[i])=='a'-'A')                    s.pop();                else if(str[i]=='%'&&islower(s.top()))                    s.pop();                else if(s.top()=='%'&&islower(str[i]))                    s.pop();                else                    s.push(str[i]);            }            else                s.push(str[i]);        puts(s.empty()?"Yes":"No");        while(!s.empty())            s.pop();    }}

  说实话这次的题没啥激动人心的……大都是数据结构的基础操作,过3题以上才算比较理想(可能我想多了)……

0 0
原创粉丝点击