2016 "Bird Cup" ICPC7th@ahstu--“波导杯”安徽科技学院第七届程序设计大赛

“波导杯”安徽科技学院第七届程序设计大赛

原文章网页


Contest - 2016 "Bird Cup" ICPC7th@ahstu

Start time:  2016-04-23 08:00:00.0  End time:  2016-04-23 12:00:00.0
Current System Time:  2016-04-23 19:02:17.554  Contest Status:   Ended

关于举办“波导杯”安徽科技学院第七届程序设计大赛通知

ACM 国际大学生程序设计竞赛 (International Collegiate Programming Contest)是由美国计算机协会(ACM)主办的一项旨在展示大学生创新能力、团队精神和在压力下编写程序、分析和解决问题能力的著名竞赛。2010年以来,我校参与了历届安徽省 ACM 程序设计竞赛,并取得了优异的成绩。为选拔校 ACM 参赛队员,将举办波导杯” 安徽科技学院第七届计算机程序设计大赛,热忱欢迎广大程序设计爱好者踊跃参加。

主办方:安徽科技学院教务处、信息与网络工程学院

承办方:信息与网络工程学院

赞助方:宁波波导软件有限公司(独家赞助)

一、 比赛时间:2016  4 23(周六)上午 8:0012:00

二、比赛地点:计算机与网络实验中心(力行楼六楼)

三、比赛设奖:设一等奖8%、二等奖12%、三等奖15%

六、竞赛相关:

竞赛语言:C/C++/JAVA 环境:DevCpp /CodeBlock /Eclipse

比赛试题:采用 ICPC 样式——赛题 810

注意事项:

·  1. 练习比赛网站(安科 OJ):http://183.167.205.82:8081/JudgeOnline/

·  2. 计算机系 ACM/ICPC 学生活动室位于力行楼六楼,欢迎交流。

比赛 QQ 群:173592864(波导杯第七届校ACM赛)


Problem IdTitle
1366 Problem ADotaer vs Loler
1367 Problem Bso so so easy

1368 Problem C反转链表

1369 Problem D贪吃蛇

1370 Problem E均分硬币

1371 Problem F丢啊丢啊丢手绢

1372 Problem G分糖果
1373 Problem H埋炸弹啦~

1374 Problem I化学老师的惩罚
1375 Problem J水题!

[Standings]  [Status]  [Statistics]


Dotaer vs Loler


Time Limit:1000MS Memory Limit:65536K
Total Submit:170 Accepted:31

Description

小杨是一名Dota资深玩家,和众多Dota玩家一样,他和周围一群LOL玩家在一起有一种自然的优越感,然而身边的刀友确一个个投入了撸狗的行列,直到现在周围再没了
一个同行。。。他很愤慨,于是有了下面这道题目:
两个分别只含有Dotaer和Loler中的字母的字符串,长度(<10^6),请你分别统计两个字符串中所含字母能够组成Dotaer和Loler的最大数量(不区分大小写),然后根
据两者的数量判断输赢,若Loler数量大于Dotaer数量的3倍,则Loler win,反之Dotaer win。

Input

每个输入包含多个测试用例,每个测试用包括两行,第一行为构成Dotaer的字符串,第二行为构成Loler的字符串。

Output

对于每个测试用例输出三行,第一行为Dotaer数量,第二行为Loler数量,第三行为哪方win。

Sample Input

otdarrreoddtooaaoooee
rolereoreolrereoreol

Sample Output

Dotaer: 2
Loler: 1
Dotaer win

Source

icpc7th@ahstu

#include<iostream>
#include<string>
#include<map>
#include<fstream>
using namespace std;
map<char,int>Dota;
map<char,int>LOL;
map<char,int>::iterator d_it;
map<char,int>::iterator l_it;
char change(char a)
{
   return (a<97)?(a+32):a;
}
void print()
{
    for(d_it=LOL.begin();d_it!=LOL.end();d_it++)
    {
        cout<<d_it->second<<" "<<d_it->first<<endl;
    }
}
int dota(string D)
{
    for(int i=0;i<D.size();i++)
    {
        Dota[change(D[i])]++;
    }
    Dota['d'];Dota['o'];
    Dota['t'];Dota['a'];
    Dota['e'];Dota['r'];
    int m=1000001;
   for(d_it=Dota.begin();d_it!=Dota.end();d_it++)
   {
       if(m>(d_it->second))
        m=(d_it->second);
   }
   return m;
}
int lol(string L)
{
     for(int i=0;i<L.size();i++)
    {
        LOL[change(L[i])]++;
    }
    LOL['l']; LOL['o'];
    LOL['e']; LOL['r'];
    int m=1000001;
    for(l_it=LOL.begin();l_it!=LOL.end();l_it++)
    {
        if((l_it->first)!='l')
        {
            if(m>(l_it->second))
                m=l_it->second;
        }
        else
        {
            if(m>(l_it->second)/2)
                m=(l_it->second)/2;
        }
    }
    return m;
}
int main()
{
    //freopen("Dotaer vs Loler.in","r",stdin);
    //freopen("Dotaer vs Loler.out","w",stdout);
    string D,L;
    int D_num,L_num;
    while(cin>>D>>L)
    {
       D_num=dota(D);
       L_num=lol(L);
       cout<<"Dotaer: "<<D_num<<endl;
       cout<<"Loler: "<<L_num<<endl;
       if(L_num>3*D_num)
        cout<<"Loler win"<<endl;
       else
       cout<<"Dotaer win"<<endl;
       Dota.clear();
       LOL.clear();
    }
    return 0;
}

so so so easy


Time Limit:1000MS Memory Limit:65536K
Total Submit:46 Accepted:14

Description

为了避免打光头的情况出现,仁慈的老赵在每次比赛中总会想方设法的加水题进去,一个两个三个…..。
现有一个完全由被空格所分开的英文单词构成的字符串(单词数量<=100),请你数出每个单词是连续第几次出现。(例如 so so so easy 结果为 1 2 3 1)

Input

每个输入包含多个测试用例,每个测试用例为一个完全由被空格所分开的英文单词构成的字符串。

Output

对于每个测试用例,输出其每个单词是连续第几次出现。

Sample Input

so so so easy so so

Sample Output

1 2 3 1 1 2

Source

icpc7th@ahstu

#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
using namespace std;
void easy(string A)
{
    int i;
    int num=0;
    string flag;
    string B[100];
    istringstream sin(A);
    for(i=0;sin>>B[i];i++);
    flag="";
    for(int j=0;j<i;j++)
    {
        if(B[j]!=flag)
        {
            num=1;
            flag=B[j];
            cout<<num<<" ";
        }
        else
        {
            num++;
            cout<<num<<" ";
        }
    }
    cout<<endl;
}
int main()
{
   // freopen("so so so easy.in","r",stdin);
   // freopen("so so so easy.out","w",stdout);
    string A;
    while(getline(cin,A))
    {
        easy(A);
    }
    return 0;
}

反转链表


Time Limit:1000MS Memory Limit:65536K
Total Submit:5 Accepted:0

Description

给定一个常数K以及一个单链表L,请编写程序将L中每K个结点反转。例如:给定L为1→2→3→4→5→6,K为3,则输出应该为3→2→1→6→5→4;如果K为4,则输出应该为4→3→2→1→5→6,即最后不到K个元素不反转。

Input

每个输入包含多个测试用例。每个测试用例第1行给出第1个结点的地址、结点总个数正整数N(<= 105)、以及正整数K(<=N),即要求反转的子链结点的个数。结点的地址是5位非负整数,NULL地址用-1表示。

接下来有N行,每行格式为:

Address Data Next

其中Address是结点地址,Data是该结点保存的整数数据,Next是下一结点的地址。

Output

对每个测试用例,顺序输出反转后的链表(每个节点的 Address Data Next),其上每个结点占一行,格式与输入相同。

Sample Input

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

Source

icpc7th@ahstu

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<stdio.h>
    #include<cstdlib>
    #include<fstream>
    using namespace std;

    typedef struct
    {
        int add;
        int data;
        int next;
    }Node;
    Node L[100001];
    vector<Node>N;
    vector<Node>::iterator it;
    int scan(int &Add,int &num,int &n)
    {
        Node N;
        for(int i=0;i<num;i++)
        {
            cin>>N.add>>N.data>>N.next;
            L[N.add]=N;
        }
        return 1;
    }
    void L_sort(int start,int n)
    {
         int flag=start;
         while(flag!=-1)
         {
             N.push_back(L[flag]);
             flag=L[flag].next;
         }
    }
    void F_sort(int n)
    {
        int G=N.size()/n;
        for(int i=0;i<G;i++)
        {
            reverse((N.begin()+i*n),(N.begin()+(i+1)*n));
        }
    }
    void print()
    {
        for(it=N.begin();it<N.end()-1;it++)
        {
            printf("%05d %d %05d\n",(*it).add,(*it).data,(*(it+1)).add);
        }
                printf("%05d %d -1\n",(*(N.end()-1)).add,(*(N.end()-1)).data);
    }
    int main()
    {
       int Add,num,n;
        //freopen("反转链表.in","r",stdin);
        //freopen("反转链表.out","w",stdout);
        while(cin>>Add>>num>>n)
        {
            scan(Add,num,n);
           L_sort(Add,n);
           F_sort(n);
           print();
           N.clear();
        }
        return 0;
    }

贪吃蛇


Time Limit:1000MS Memory Limit:65536K
Total Submit:9 Accepted:2

Description

有童年的孩子都玩过这个经典游戏,不过这里的规则又有点不同,现在有一个N*M(N,M<=100)的方形矩形,在这个矩形的每一个方格上都放有若干个樱桃,一条可爱的小蛇从矩形的
左上角开始出发,每次移动都只能移动一格,向右或向下,而每到达一格贪吃的小蛇都会吧该位置上的樱桃吃个一干二净,直到到达右下角时停止。而贪吃的小蛇不怕撑死,它只想吃到最多
的樱桃,请你告诉它他最多能吃到多少樱桃以及具体路线吧。(数据保证最优路线只有一条)

Input

每个输入包含多个测试用例,每个测试用例第一行给出N,M,接下来N行M列数据代表每个位置上的樱桃个数。(矩阵坐标从(1,1)开始)。

Output

对于每个测试用例输出第一行为能吃到的最大樱桃个数,接下来为小蛇所需要走的路线的坐标,每个坐标占一行。

Sample Input

4 4
1 2 3 7
3 4 2 1
1 5 4 8
10 3 0 3

Sample Output

28
(1,1)
(2,1)
(2,2)
(3,2)
(3,3)
(3,4)
(4,4)

Source

icpc7th@ahstu

    #include<iostream>
    #include<string>
    #include<fstream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef struct
    {
        int m_sum;
        vector<string> way;
    }MP;
    int mp[102][102];
    MP Mp[102][102];
    int N,M;
    string change(int a)
    {
        string A;
        while(a!=0)
        {
            A+=((a%10)+'0');
            a/=10;
        }
        reverse(A.begin(),A.end());
        return A;
    }
    void scan()
    {
        for(int i=0;i<=M;i++)
            mp[0][i]=0;
        for(int i=0;i<=N;i++)
            mp[i][0]=0;
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j<=M;j++)
            cin>>mp[i][j];
        }
    }
    void hand_mp()
    {
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j<=M;j++)
            {
                Mp[i][j].m_sum=mp[i][j]+((mp[i][j-1]>=mp[i-1][j])?mp[i][j-1]:mp[i-1][j]);
                mp[i][j]= Mp[i][j].m_sum;
                Mp[i][j].way=(mp[i][j-1]>=mp[i-1][j])?(Mp[i][j-1]).way:(Mp[i-1][j]).way;
                Mp[i][j].way.push_back(change(i));
                Mp[i][j].way.push_back(change(j));
            }
        }
    }
    void print()
    {
        cout<<Mp[N][M].m_sum<<endl;
        for(int i=0;i<Mp[N][M].way.size();i+=2)
        {
            cout<<"("<<Mp[N][M].way[i]<<","<<Mp[N][M].way[i+1]<<")"<<endl;
        }
    }
    int  main()
    {
       // freopen("贪吃蛇.in","r",stdin);
       // freopen("贪吃蛇.out","w",stdout);
        while(cin>>N>>M)
        {
            scan();
            hand_mp();
            print();
        }
        return 0;
    }

均分硬币


Time Limit:1000MS Memory Limit:65536K
Total Submit:14 Accepted:4

Description

有N堆硬币,编号分别为 1,2,…, N(N<=100) 每堆上有若干个硬币,可以在任一堆上取若干个硬币,然后移动。移动规则为:在编号为 1 堆上取的硬币,只能移到编号为 2 的堆上;
在编号为 N 的堆上取的硬币,只能移到编号为 N-1 的堆上;其他堆上取的硬币,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上硬币
数都一样多。例如 N=4,4 硬币数分别为: ① 9 ② 8 ③ 17 ④ 6 移动3次可达到目的。

Input

每个输入包含多个测试用例,每个测试用例第一行为整数N硬币堆数,接下来一行N个数为相应堆上硬币的数量。

Output

对于每个测试用例,输出其最少需要移动次数,若无法均分则输出“Oh no!”

Sample Input

4
9 8 17 6

Sample Output

3

Source

icpc7th@ahstu

    #include<iostream>
    #include<fstream>
    using namespace std;
    int avg(int *A,int n)
    {
        int sum=0;
        int avge;
        int flag=0;
        for(int i=0;i<n;i++)
            sum+=A[i];
        avge=sum/n;
        if(avge*n==sum)
        {
            for(int i=0;i<n-1;i++)
            {
                if(A[i]!=avge)
                {
                    A[i+1]+=A[i]-avge;
                    flag++;
                }

            }
            cout<<flag<<endl;
        }
        else
            cout<<"Oh no!"<<endl;
    }
    int main()
    {
        int N;
        int A[101];
        while(cin>>N)
        {
            for(int i=0;i<N;i++)
                cin>>A[i];
            avg(A,N);
        }
        return 0;
    }

丢啊丢啊丢手绢


Time Limit:1000MS Memory Limit:65536K
Total Submit:17 Accepted:4

Description

在安科图书馆前的草地上围坐着N个同学1,2,3,…..N.(按顺序围成一个圈),然后从其中一个同学开始,拿着一手绢按编号从小到大的方向一步一步绕着圈子走,
一步经过一个同学,若干步后把手绢交给面前的同学,接到手绢的同学不改变方向用同样的方式把手绢交给另一个同学后淘汰出游戏,凡是一个同学离开圈子,剩下同学
把空缺消除再构成一个圆(相对位置不变)。现在告诉你开始同学的编号和手帕n次行进的步数,你知道终剩下哪些同学吗?

Input

每个输入包含多个测试用例,每个测试用例包括两部分:
第一部分三个数字num(参与游戏学生总数),i(初始学生编号),n(手绢移动的次数)。
第二部分n个整数为n次手绢分别移动的步数。

Output

输出游戏结束后所剩学生的编号(按升序输出)。

Sample Input

6 2 3
2 3 4

Sample Output

5 6

Source

icpc7th@ahstu

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<fstream>
    using namespace std;
    void init(vector<int> &A,int num)
    {
        for(int i=0;i<=num;i++){
            A.push_back(i);
        }
    }
    void game(vector<int> A,int *way,int n,int first)
    {
        int index;
         A.erase(A.begin()+first);
         index=first-1;
        for(int i=0;i<n;i++)
        {
            A.erase(A.begin()+(index+way[i])%A.size());
            index=(index+way[i])%A.size()-1;
        }
        for(int i=1;i<A.size();i++)
        cout<<A[i]<<" ";
        cout<<endl;
    }
    int main()
    {
        //freopen("¶ª°¡¶ª°¡¶ªÊÖ¾î.in","r",stdin);
        //freopen("¶ª°¡¶ª°¡¶ªÊÖ¾î.out","w",stdout);
        int num,first,n;
        vector<int> A;
        int way[100];
        while(cin>>num>>first>>n)
        {
            for(int i=0;i<n;i++)
                cin>>way[i];

            init(A,num);
             game(A,way,n,first);
             A.clear();
        }
        return 0;
    }

分糖果


Time Limit:1000MS Memory Limit:65536K
Total Submit:0 Accepted:0

Description

小洛,小欢,小涛是三个小屁孩,他们有一个共同的爱好—吃糖!小杨每天都会给他们买糖吃,但他有个要求,每次小杨会把买来的糖随机分成三堆,
(<=10^4) 三个小屁孩想要吃到糖,就必须按小杨的要求每次把任意一堆糖的一半放到其他糖堆里,最终使三堆糖的数量和小杨所要求的完全一致,才被允许吃.
(若一堆糖为奇数个,它的一半为较少的那部分)。那么他们最少需要移动多少次才能吃到糖果。

Input

每个输入包含多个测试用例,每个测试用例第一行给出3个数字为初始的糖堆数量,第二行3个数字为小杨要求糖堆最终数量。

Output

对于每个测试用例输出一行为其最少移动次数,若不可能达到要求输出“Unfind”。

Sample Input

6 10 3
6 5 8

1 2 5
3 0 5

Sample Output

1
Unfind

Source

icpc7th@ahstu

    #include<iostream>
    #include<queue>
    #include<string>
    #include<map>
    #include<cstdio>
    #include<sstream>
    using namespace std;

    typedef struct
    {
        int step;
        int candy[3];
    } ST;
    map<string,int>mp;
    int init[3];
    int target[3];
    void state(ST &S,int i)
    {
        int f,s,t;
        f=S.candy[0];
        s=S.candy[1];
        t=S.candy[2];
        S.step++;
        switch(i)
        {
        case 1:
            S.candy[0]=f-f/2;
            S.candy[1]=s+f/2;
            break;
        case 2:
            S.candy[0]=f+s/2;
            S.candy[1]=s-s/2;
            break;
        case 3:
            S.candy[0]=f-f/2;
            S.candy[2]=t+f/2;
            break;
        case 4:
            S.candy[0]=f+t/2;
            S.candy[2]=t-t/2;
            break;
        case 5:
            S.candy[1]=s-s/2;
            S.candy[2]=t+s/2;
            break;
        case 6:
            S.candy[1]=s+t/2;
            S.candy[2]=t-t/2;
            break;
        }
    }
    int Search(int *init,int *target,queue<ST> &Q,int &STEP)
    {
        ST flag;
        string fl,l;
        flag.step=0;
        flag.candy[0]=init[0];
        flag.candy[1]=init[1];
        flag.candy[2]=init[2];
        Q.push(flag);
        for(int i=0; i<3; i++)
        {
            char b[15];
            sprintf(b,"%d",flag.candy[i]);
            fl+=b;
        }
        mp[fl]=1;
        if(flag.candy[0]==target[0]&&flag.candy[1]==target[1]&&flag.candy[2]==target[2])
        {
            STEP=flag.step;
            return 1;
        }
        while(!Q.empty())
        {
            flag=Q.front();
            for(int i=1; i<=6; i++)
            {
                state(flag,i);
                if(flag.candy[0]==target[0]&&flag.candy[1]==target[1]&&flag.candy[2]==target[2])
                {
                    STEP=flag.step;
                    return 1;
                }
                fl="";
                for(int i=0; i<3; i++)
                {
                    char b[15];
                    sprintf(b,"%d",flag.candy[i]);
                    fl+=b;
                }
                if(mp[fl]!=1)
                {
                    Q.push(flag);
                    mp[fl]=1;
                }
                flag=Q.front();
            }
            Q.pop();
        }
        return 0;
    }
    int main()
    {
        int f,s,t;
        int F,S,T;
        int STEP;
       // freopen("分糖果.in","r",stdin);
        //freopen("分糖果.out","w",stdout);
        while(cin>>f>>s>>t>>F>>S>>T)
        {
            if((f+s+t)!=(F+S+T))
            {
                cout<<"Unfind"<<endl;
                continue;
            }
            queue<ST> Q;
            init[0]=f;
            init[1]=s;
            init[2]=t;
            target[0]=F;
            target[1]=S;
            target[2]=T;
            if(Search(init,target,Q,STEP))
                cout<<STEP<<endl;
            else
                cout<<"Unfind"<<endl;
            mp.clear();
        }
        return 0;
    }

埋炸弹啦~


Time Limit:1000MS Memory Limit:65536K
Total Submit:47 Accepted:18

Description

小明是个埋弹专家同时也是个数学爱好者,他每次进行埋弹任务时都喜欢数字决定埋在哪里,他会选出两个数字然后分别把它们转化成八位二进制数,第一个作为横向坐标(从左往右),
第二个作为纵向(从上往下)坐标构成一个8*8的矩阵,而他埋弹的位置当然就是横竖坐标中1的交叉点。请把他埋的位置表示出来,炸弹位置用‘+’表示,其他地方用‘-’表示。

Input

每个输入包含多个测试用例,每个测试用例一行为两个整数 a,b(0<=a,b<256)为小明所选定的两个数。

Output

对于每个测试用例,输出一个8*8的矩阵,按要求表明炸弹位置。

Sample Input

9 18

Sample Output

--------
--------
--------
----+--+
--------
--------
----+--+
--------

Source

icpc7th@ahstu

    #include<iostream>
    #include<string>
    #include<fstream>
    #include<algorithm>
    using namespace std;
    string X,Y;
    int x,y;
    void init()
    {
        while(x!=0)
        {
            X+=((x%2)+'0');
            x/=2;
        }
        while(y!=0)
        {
            Y+=((y%2)+'0');
            y/=2;
        }
        reverse(X.begin(),X.end());
        reverse(Y.begin(),Y.end());
        int l1=X.size();
        int l2=Y.size();
        for(int i=0;i<8-l1;i++)
            X.insert(X.begin(),'0');
        for(int i=0;i<8-l2;i++)
            Y.insert(Y.begin(),'0');
    }
    void bomb()
    {
        for(int i=0;i<Y.size();i++)
        {
            for(int j=0;j<X.size();j++)
        {
            if(Y[i]=='1'&&X[j]=='1')
                cout<<'+';
            else
                cout<<'-';
        }
        cout<<endl;
        }
    }
    int main()
    {
        //freopen("ÂñÕ¨µ¯À²~.in","r",stdin);
       // freopen("ÂñÕ¨µ¯À²~.out","w",stdout);
        while(cin>>x>>y)
        {
            init();
            bomb();
            X="";
            Y="";
        }
        return 0;
    }

化学老师的惩罚


Time Limit:1000MS Memory Limit:65536K
Total Submit:0 Accepted:0

Description

小明的化学成绩很差,他的老师对他恨铁不成钢啊,于是想了一个法子——把他关在了一个密室里,出不来不给吃饭。这个把小明急坏了。。
小明发现密室的墙上写了许多化学方程式中。化学方程式,也称为化学反应方程式,是用化学式表示物质化学反应的式子。化学方程式反映的是客观事实。因此书写化学方程式要遵守两个原则:一是必须以客观事实为基础;二是要遵守质量守恒定律。
化学方程式不仅表明了反应物、生成物和反应条件。同时,化学计量数代表了各反应物、生成物物质的量关系,通过相对分子质量或相对原子质量还可以表示各物质之间的质量关系,即各物质之间的质量比。对于气体反应物、生成物,还可以直接通过化学计量数得出体积比。例如:2NaOH+H2SO4=Na2SO4+2H2O
经过多次试探、推理,小明发现密码是4位数字,就隐藏在化学方程式等号后的第一个分子中,其分子量就可能是密码(若分子量不足4位,前面加0)。

好在小明还记得墙上各化学方程式用到的化学元素的原子量如下:

N | C | O | Cl | S | H | Al | Ca | Zn | Na | B | Ni

14 | 12 | 16 | 35 | 32 | 2 | 27 | 40 | 65 | 23 | 11 | 59

你能帮小明尽快找到密码吗?

Input

输入包含多组测试用例。
每个测试用例 第一行: K,表示有K个化学方程式;
接下来有K行,每行为一个化学方程式

Output

对于每个化学方程式输出一行:即密码。

Sample Input

2
2C+O2=2CO
Ca2CO3+H2O=Ca2(OH)2+CO2

Sample Output

0056
0116

Source

icpc7th@ahstu

    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<iterator>
    #include<vector>
    #include<map>
    #include<cstdlib>
    #include<cstdio>
    #include<fstream>
    using namespace std;
    map<string,int>mp;
    vector<string>sp;
    vector<string>sp_num;
    string total;
    void init()
    {
        mp["Na"]=23;mp["Zn"]=65;
        mp["Ca"]=40;mp["Al"]=27;
        mp["H"]=2;  mp["S"]=32;
        mp["Cl"]=35;mp["O"]=16;
        mp["C"]=12; mp["N"]=14;
         mp["B"]=11; mp["Ni"]=59;
    }
    int calculate(string B)
    {
        int sum=0;
        for(int i=0; i<B.size(); i++)
        {
            string flag;
            flag+=B[i];
            flag+=B[i+1];
            if(mp[flag]!=0)
            {
                int f=i+2;
                string n;
                while(isdigit(B[f]))
                {
                    n+=B[f];
                    f++;
                }
                if(n=="")
                    n="1";
                i=(--f);
                sum+=mp[flag]*atoi(n.c_str());
            }
            else
            {
                int l=i+1;
                string n;
                while(isdigit(B[l]))
                {
                    n+=B[l];
                    l++;
                }
                if(n=="")
                    n="1";
                string K;
                K+=B[i];
                sum+=mp[K]*atoi(n.c_str());
                i=(--l);
            }
        }
        return sum;
    }
    int T_calculate()
    {
        int S=0;
        for(int i=0; i<sp.size(); i++)
        {
            S+=calculate(sp[i])*(atoi(sp_num[i].c_str()));
        }
        return S*atoi(total.c_str());
    }
    void Find(string A)
    {
        string B;
        string::iterator it;
        for(it=(find(A.begin(),A.end(),'=')+1); it!=A.end(); it++)
        {
            if(*it=='+')
                break;
            B+=(*it);
        }
        while(isdigit(B[0]))
        {
            total+=B[0];
            B.erase(B.begin());
        }
        if(total=="")
            total="1";
        string flag;
        int o=3;
        while(!B.empty())
        {
            if(o==0)
                while(1);
            o--;
            if(B[0]=='(')
            {
                string::iterator it,it1;
                string F;
                it=find(B.begin(),B.end(),')');
                F.assign(B.begin()+1,it);
                sp.push_back(F);
                F="";
                it1=(++it);
                while(isdigit((*it))&&it!=B.end())
                {
                    F+=*it;
                    it++;
                }
                if(F=="")
                    sp_num.push_back("1");
                else
                    sp_num.push_back(F);
                B.erase(B.begin(),(it));
            }
            else
            {
                string flag;
                string::iterator it=(find(B.begin(),B.end(),'('));
                flag.assign(B.begin(),(it));
                sp.push_back(flag);
                B.erase(B.begin(),(it));
                sp_num.push_back("1");
            }
        }
    }
    int main()
    {
        //freopen("化学老师的惩罚.in","r",stdin);
        //freopen("化学老师的惩罚.out","w",stdout);
        int N;
        init();
        while(cin>>N)
        {
        while(N--)
        {
            string A;
            cin>>A;
            Find(A);
            printf("%04d\n",T_calculate());
            sp.clear();
            sp_num.clear();
            total="";
        }
        }
        return 0;
    }

水题!


Time Limit:1000MS Memory Limit:65536K
Total Submit:116 Accepted:44

Description

杯子高H,水高h,杯顶半径R,杯底半径r,求水的体积。(Pi=3.1415926)

Input

H R r h

Output

水的体积

Sample Input

10 8 7 4

Sample Output

855.56

Hint

圆台计算公式V=1/3*Pi*h*(R^2+r^2+R*r)

Source

icpcth7@ahstu

posted @ 2016-04-24 17:29  范晋豪  阅读(179)  评论(0编辑  收藏  举报