zoukankan      html  css  js  c++  java
  • CUGBACM Codeforces Tranning 1 题解

    链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=61581#overview

    描写叙述:非常老的CF题,题不错,拿来训练正好。

    做的时候刚做完BC,还时不时去hdu看看有木有judge结束,题有木有挂掉,脑子有点糊涂,当时过了三题(按自己平时做CF的顺序作的)。代码写得也非常繁琐(就记得B题T成狗,最后在群里的提醒下过了...)。当然如今脑子也是糊涂。打完北京赛区然后就要连续考试三门我也是醉了。

    要不是立即比赛就要关了赛后AK的时间预计还要再往后拖他个几天...无论是不是退役这样的比赛确实是做一场少一场了,写个解题报告留个念吧。

    题解:

    A.Before an Exam

    题意:给出天数和总共要学习的小时数。而且给出每天能学习的最长时间和最短时间,问能不能正常完毕任务。

    思路:直接找到上限下限看在不在当中就可以。

    代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <ctype.h>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    #define eps 1e-8
    #define INF 0x7fffffff
    #define maxn 10005
    #define PI acos(-1.0)
    #define seed 31//131,1313
    //#define LOCAL
    typedef long long LL;
    typedef unsigned long long ULL;
    using namespace std;
    const LL MOD = 1000000007 ;
    int Min[35],Max[35];
    bool vis[35];
    int n[35];
    int main()
    {
        #ifdef LOCAL
        freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        #endif
        int a,b;
        scanf("%d%d",&a,&b);
        int Lim_min=0,Lim_max=0;
        for(int i=1;i<=a;i++)
        {
            scanf("%d%d",&Min[i],&Max[i]);
            Lim_min+=Min[i];
            Lim_max+=Max[i];
        }
        if(b>Lim_max||b<Lim_min)
            puts("NO");
        else
        {
            puts("YES");
            for(int i =1;i<=a;i++)
            {
                //cout<<n[i]<<Min[i];
                n[i]=Min[i];
                //cout<<n[i]<<Min[i]<<endl;
            }
            int sub=b-Lim_min;
            for(int i=1;i<=a;i++)
            {
                if(sub==0)
                    break;
                else
                {
                    //cout<<i<<" "<<Max[i]<<" "<<Min[i]<<" "<<n[i]<<endl;
                    //cout<<sub<<endl;
                    n[i]+=min(Max[i]-n[i],sub);
                    sub-=n[i]-Min[i];
                }
            }
            for(int i=1;i<=a;i++)
                if(i!=1)
                printf(" %d",n[i]);
            else printf("%d",n[i]);
            printf("
    ");
        }
        return 0;
    }

    B.The least round way

    题意:给出一个n*n的矩阵(每一个点的值都是非负数),初始数值是1,从矩阵左上角走到矩阵右下角走出一条路径。把沿途的全部数都乘到自己身上,问最后后缀有多少个0。

    思路:简单DP,从左上向右下推两次。第一次找到能够得到的2的最少数。第二次找到能够得到的5的最少数,两次推得的比較少的数量就是后缀0的最少数。

    特殊情况是矩阵中存在0的情况,假设所得的最优路径上得到的后缀0数超过1个。那么就取经过0的路径。这样后缀0就仅仅有1个。

    代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <ctype.h>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    #define eps 1e-8
    #define INF 0x7fffffff
    #define maxn 10005
    #define PI acos(-1.0)
    #define seed 31//131,1313
    //#define LOCAL
    typedef long long LL;
    typedef unsigned long long ULL;
    using namespace std;
    int M[1005][1005];
    int a[1005][1005][2];
    int dp2[1005][1005],dp5[1005][1005];
    int from2[1005][1005],from5[1005][1005];//1是上。2是左
    int main()
    {
    #ifdef LOCAL
        freopen("out.txt", "r", stdin);
        //freopen("in.txt", "w", stdout);
    #endif
        int t;
        scanf("%d",&t);
        bool flag = 0;
        int tox = -1, toy= -1;
        for(int i=0; i<t; i++)
            for(int j=0; j<t; j++)
            {
                scanf("%d",&M[i][j]);
                if(M[i][j]==0)
                {
                    tox=i;
                    toy=j;
                    flag = 1;
                }
    
                int ttt=M[i][j];
                if(ttt!=0)
                {
                    while(ttt%2==0&&ttt!=0)
                    {
                        a[i][j][0]++;
                        ttt/=2;
                    }
                    ttt=M[i][j];
                    while(ttt%5==0&&&ttt!=0)
                    {
                        a[i][j][1]++;
                        ttt/=5;
                    }
                }
                if(i==0&&j==0)
                {
                    dp2[0][0]=a[0][0][0];
                    dp5[0][0]=a[0][0][1];
                }
                else
                {
                    if(i==0)
                    {
                        dp2[i][j]=dp2[i][j-1]+a[i][j][0];
                        from2[i][j]=2;
                    }
                    else if(j==0)
                    {
                        dp2[i][j]=dp2[i-1][j]+a[i][j][0];
                        from2[i][j]=1;
                    }
                    else
                    {
                        if(dp2[i][j-1]<dp2[i-1][j])
                        {
                            dp2[i][j]=dp2[i][j-1]+a[i][j][0];
                            from2[i][j]=2;
                        }
                        else
                        {
                            dp2[i][j]=dp2[i-1][j]+a[i][j][0];
                            from2[i][j]=1;
                        }
                    }
                    if(i==0)
                    {
                        dp5[i][j]=dp5[i][j-1]+a[i][j][1];
                        from5[i][j]=2;
                    }
                    else if(j==0)
                    {
                        dp5[i][j]=dp5[i-1][j]+a[i][j][1];
                        from5[i][j]=1;
                    }
                    else
                    {
                        if(dp5[i][j-1]<dp5[i-1][j])
                        {
                            dp5[i][j]=dp5[i][j-1]+a[i][j][1];
                            from5[i][j]=2;
                        }
                        else
                        {
                            dp5[i][j]=dp5[i-1][j]+a[i][j][1];
                            from5[i][j]=1;
                        }
                    }
                }
            }
        char ss[2005];
        int top = 0;
        if(dp2[t-1][t-1]<dp5[t-1][t-1])
        {
            if(flag == 1 && dp2[t-1][t-1]>1)
            {
                printf("1
    ");
                for(int i=0;i<tox;i++)
                    printf("D");
                for(int i=1;i<t;i++)
                    printf("R");
                for(int i=tox+1;i<t;i++)
                    printf("D");
                    return 0;
            }
            printf("%d
    ",dp2[t-1][t-1]);
            int row=t-1;
            int col=t-1;
            while(row||col)
            {
                if(from2[row][col]==2)
                {
                    ss[top++]='R';
                    col--;
                }
                else
                {
                    ss[top++]='D';
                    row--;
                }
            }
            for(int i=top-1; i>=0; i--)
                printf("%c",ss[i]);
        }
        else
        {
            if(flag == 1 && dp5[t-1][t-1]>1)
            {
                printf("1
    ");
                for(int i=0;i<tox;i++)
                    printf("D");
                for(int i=1;i<t;i++)
                    printf("R");
                for(int i=tox+1;i<t;i++)
                    printf("D");
                return 0;
            }
            printf("%d
    ",dp5[t-1][t-1]);
            int row=t-1;
            int col=t-1;
            while(row||col)
            {
                if(from5[row][col]==2)
                {
                    ss[top++]='R';
                    col--;
                }
                else
                {
                    ss[top++]='D';
                    row--;
                }
            }
            for(int i=top-1; i>=0; i--)
                putchar(ss[i]);
        }
        return 0;
    }


    C.Tic-tac-toe

    题意:给出一个棋盘(三子棋),给出棋盘的情况,'X'是第一个人的棋子。'0'是第二个人的棋子,'.'是空的。

    来推断棋盘情况是否合法。假设合法,推断是否有人赢,假设没有人赢,假设没人赢且棋盘没满。则输出下一步谁走,否则输出平局。

    思路:模拟搞搞搞。说一下我找到的最后一种情况吧,"XXX

                                                                                                     00. 

                                                                                                     . . 0"是不合法的。

    由于第一个人赢了,游戏就结束了,第二个人就不用下了。

    代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <ctype.h>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    #define eps 1e-8
    #define INF 0x7fffffff
    #define maxn 10005
    #define PI acos(-1.0)
    #define seed 31//131,1313
    //#define LOCAL
    typedef long long LL;
    typedef unsigned long long ULL;
    using namespace std;
    char ss[5][5];
    int ac[3],ar[3],bc[3],br[3],ax[3],bx[3];
    int judge()
    {
        if(ss[0][0]==ss[0][1]&&ss[0][0]==ss[0][2])
        {
            if(ss[0][0]=='X')
                ar[0]=1;
            else if(ss[0][0]=='0')
                br[0]=1;
        }
        if(ss[1][0]==ss[1][1]&&ss[1][0]==ss[1][2])
        {
            if(ss[1][0]=='X')
                ar[1]=1;
            else if(ss[1][0]=='0')
                br[1]=1;
        }
        if(ss[2][0]==ss[2][1]&&ss[2][0]==ss[2][2])
        {
            if(ss[2][0]=='X')
                ar[2]=1;
            else if(ss[2][0]=='0')
                br[2]=1;
        }
        if(ss[0][0]==ss[1][0]&&ss[0][0]==ss[2][0])
        {
            if(ss[0][0]=='X')
                ac[0]=1;
            else if(ss[0][0]=='0')
                bc[0]=1;
        }
        if(ss[0][1]==ss[1][1]&&ss[0][1]==ss[2][1])
        {
            if(ss[0][1]=='X')
                ac[1]=1;
            else if(ss[0][1]=='0')
                bc[1]=1;
        }
        if(ss[0][2]==ss[1][2]&&ss[0][2]==ss[2][2])
        {
            if(ss[0][2]=='X')
                ac[2]=1;
            else if(ss[0][2]=='0')
                bc[2]=1;
        }
        if(ss[0][0]==ss[1][1]&&ss[0][0]==ss[2][2])
        {
            if(ss[0][0]=='X')
                ax[0]=1;
            if(ss[0][0]=='0')
                bx[0]=1;
        }
        if(ss[0][2]==ss[1][1]&&ss[2][0]==ss[1][1])
        {
            if(ss[0][2]=='X')
                ax[1]=1;
            if(ss[0][2]=='0')
                bx[1]=1;
        }
    //    for(int i=0;i<3;i++)
    //        cout<<ac[i]<<" "<<bc[i]<<" "<<ar[i]<<" "<<br[i]<<endl;
    //cout<<ac[0]<<ac[1]<<ac[2]<<ar[0]<<ar[1]<<ar[2]<<ax[0]<<ax[1]<<" "<<bc[0]<<bc[1]<<bc[2]<<br[0]<<br[1]<<br[2]<<bx[0]<<bx[1]<<endl;
        if(ac[0]+ac[1]+ac[2]+ar[0]+ar[1]+ar[2]+ax[0]+ax[1]>0&&bc[0]+bc[1]+bc[2]+br[0]+br[1]+br[2]+bx[0]+bx[1]>0)
            return 3;
        if(ac[0]+ac[1]+ac[2]>1)
            return 3;
        else if(bc[0]+bc[1]+bc[2]>1)
            return 3;
        else if(ar[0]+ar[1]+ar[2]>1)
            return 3;
        else if(br[0]+br[1]+br[2]>1)
            return 3;
        else if(ac[0]+ac[1]+ac[2]==1)
            return 1;
        else if(ar[0]+ar[1]+ar[2]==1)
            return 1;
        else if(br[0]+br[1]+br[2]==1)
            return 2;
        else if(bc[0]+bc[1]+bc[2]==1)
            return 2;
        else if(ax[0]+ax[1]>0)
            return 1;
        else if(bx[0]+bx[1]>0)
            return 2;
        return 0;
    }
    int main()
    {
        #ifdef LOCAL
        //freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
        #endif
        int aa=0,bb=0;
        for(int i=0;i<3;i++)
            scanf("%s",ss[i]);
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
            {
                if(ss[i][j]=='X')
                    aa++;
                else if(ss[i][j]=='0')
                    bb++;
            }
        }
        if(aa-bb>1||aa<bb)
            puts("illegal");
        else
        {
            if(aa+bb!=9)
            {
                int k=judge();
                if(k==1)
                {
                    if(aa>bb)
                        puts("the first player won");
                    else puts("illegal");
                }
                else if(k==2)
                {
                    if(aa==bb)
                        puts("the second player won");
                    else puts("illegal");
                }
                else if(k==3)
                    puts("illegal");
                else if(aa>bb)
                    puts("second");
                else puts("first");
            }
            else
            {   int k=judge();
                if(aa!=5)
                    puts("illegal");
                else if(k==1)
                    puts("the first player won");
                else if(k==2)
                    puts("the second player won");
                else if(k==3)
                    puts("illegal");
                else puts("draw");
            }
        }
        return 0;
    }


    D.Ancient Berland Circus

    题意:给一个三个顶点,问以这三个点为顶点的正N边行(N<=100)的最小面积是多少。

    思路:首先找到这个三角形的外切圆的圆心(正弦余弦定理),然后算出半径,然后从三角形開始枚举,到一百边形(边越少面积越小)。我居然由于开了100*100的数组越界RE。哈哈哈哈

    代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <ctype.h>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    #define eps 1e-8
    #define INF 0x7fffffff
    #define maxn 13
    #define PI acos(-1.0)
    #define seed 31//131,1313
    typedef long long LL;
    using namespace std;
    double corner[105][105] ;
    double x[5],y[5];
    void init()
    {
        for(int i = 3 ; i <= 100 ; i ++)
        {
            corner[i][1] = 2 * PI / (1.0 * i) ;
            for(int j = 2 ; j <= i ; j ++)
            {
                //if(i<10)
                corner[i][j]=corner[i][j-1]+corner[i][1];
                //cout<<corner[i][j]<<" ";
            }
            //cout<<endl;
        }
    }
    int main()
    {
        init();
        for(int i = 0 ; i < 3 ; i ++)
        {
            cin>>x[i]>>y[i];
            //cout<<x[i]<<" "<<y[i]<<endl;
        }
        double a = sqrt ( (x[1] - x[0])*(x[1] - x[0]) + (y[1] - y[0])*(y[1] - y[0]) ) ;
        double b = sqrt ( (x[2] - x[0])*(x[2] - x[0]) + (y[2] - y[0])*(y[2] - y[0]) ) ;
        double c = sqrt ( (x[2] - x[1])*(x[2] - x[1]) + (y[2] - y[1])*(y[2] - y[1]) ) ;
        double cosa = (b * b + c * c - a * a) / (2 * b * c ) ;
        double sina = sqrt (1 - cosa * cosa) ;
        double r = a / (2 * sina) ;
        double aa = asin (a / 2 / r) * 2 ;
        double bb = asin (b / 2 / r) * 2 ;
        double cc = asin (c / 2 / r) * 2 ;
        //printf("%lf %lf %lf
    ",aa,bb,cc);
        int flag1 = 0 , flag2 = 0 , flag3 = 0;
        for(int i = 3 ; i <= 100 ; i ++)
        {
            flag1 = 0 ;
            flag2 = 0 ;
            flag3 = 0 ;
            for(int j = 1 ; j <= i ; j ++)
            {
                if(fabs(aa - corner[i][j])<1e-6)
                    flag1 = 1;
                if(fabs(bb - corner[i][j])<1e-6)
                    flag2 = 1;
                if(fabs(cc - corner[i][j])<1e-6)
                    flag3 = 1;
            }
            //printf("%d %d %d
    ",flag1,flag2,flag3);
            if(flag1 + flag2 + flag3 ==3)
            {
                //cout<< i << endl;
                double s = 2 * PI / (1.0 * i) ;
                double ledge = sqrt(r * r + r * r - 2 * r * r * cos (s));
                //cout<<ledge<<endl;
                double p = (r + r + ledge) / 2;
                double ans = sqrt(p * (p - r) * (p - r) * (p - ledge)) * (1.0*i);
                printf("%.8lf
    ",ans);
                break;
            }
        }
        return 0;
    }

    E.Least Cost Bracket Sequence

    题意:类似括号匹配的问题给出一个括号序列,中间存在问号。假设出现问号。能够选择将它变成‘(’或者‘)’,然后两种变形分别有所花费,问花费最少的能使全括号匹配的方式,不存在输出-1。

    思路:从左到右每出现一个‘)’要保证它左边(包含本身)的’(‘数大于等于')’就可以。

    这样每出现问号直接变成‘)’,假设出现不符合条件的情况就挑左边中一个能添加花费最少的‘?’变成‘(’。

    代码:

    #include <algorithm>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <ctype.h>
    #include <iostream>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    #define eps 1e-8
    #define INF 0x7fffffff
    #define maxn 13
    #define PI acos(-1.0)
    #define seed 31//131,1313
    //#define LOCAL
    typedef long long LL;
    typedef unsigned long long ULL;
    using namespace std;
    char ss[500005];
    struct Wenhao {
        LL cost;
        int pos;
    }wenhao;
    bool operator < (const Wenhao a,const Wenhao b)
    {
        return a.cost<b.cost;
    }
    priority_queue <Wenhao> q ;
    int main()
    {
        scanf("%s",ss);
        int len = strlen(ss);
        int top = 0 ;
        int res = 0 ;
        LL ans = 0 ;
        for(int i=0;i<len;i++)
        {
            if(ss[i]=='?')
            {
                res--;
                LL a,b;
                scanf("%lld%lld",&a,&b);
                wenhao.cost = b - a ;
                wenhao.pos = i;
                q.push(wenhao);
                ss[i] = ')';
                ans += b  ;
            }
            else if(ss[i]=='(')
                    res++;
            else res--;
            if(res<0)
            {
                if(!q.empty())
                {
                    ans -= (q.top()).cost;
                    ss[q.top().pos] = '(';
                    q.pop();
                    res+=2;
                }
                else
                {
                    puts("-1");
                    return 0;
                }
            }
        }
        if(res==0)
        {
            printf("%lld
    ",ans);
            puts(ss);
        }
        else puts("-1");
        return 0;
    }


  • 相关阅读:
    APP端上传文件至服务器后台,WEB端上传文件存储到服务器
    freemarker模板引擎
    JEECG开发总结
    spring的基本配置
    jeecg解析xml文件
    jeecg查询备份
    jeecg 页面标签规则
    jeecg查询分页
    算法实践——改良的求解数独的暴力搜索法
    算法实践——舞蹈链(Dancing Links)算法求解数独
  • 原文地址:https://www.cnblogs.com/lxjshuju/p/6728229.html
Copyright © 2011-2022 走看看