组队赛#2解题总结 (BNU 第十一届北京师范大学程序设计竞赛)

比赛链接:click here~~

A BNU ACM校队时间安排,模拟~~手速题:

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
        int tmp;
        scanf("%d", &tmp);
        switch (tmp)
        {
        case 1:
            printf("Unknown\n");
            break;
        case 2:
        case 3:
            printf("Spring Training\n");
            break;
        case 4:
            printf("Spring Training\nBNU Contest\n");
            break;
        case 5:
        case 6:
            printf("Unknown\n");
            break;
        case 7:
            printf("Practice Week\nSummer Training\n");
            break;
        case 8:
            printf("Summer Training\n");
            break;
        case 9:
        case 10:
            printf("Regional Contest\n");
            break;
        case 11:
            printf("Basic Training\nRegional Contest\n");
            break;
        case 12:
            printf("Basic Training\nRookie Contest\n");
            break;
        }
    }
    return 0;
}

 B 沙漠之旅

应该是多重背包,当时没想那么多,用模拟过的。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int i,j,L,X,N;
bool flag;
int a[1005];
int aa[2100];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d%d",&L,&X,&N);
        for(int i=0; i<N; i++)
        {
            scanf("%d",&a[i]);
        }
        memset(aa,0,sizeof(aa));
        int ANS;
        for(int i=0; i<N; i++)//n^2复杂度处理两两组合
        {
            for(int j=0; j<N; j++)
            {
                ANS=a[i]+a[j];//4 5 5 6
                //cout<<ANS<<endl;
                aa[ANS]=1;
            }
        }
        bool flag=0;
        int t=L-X;//11
        for(int i=1; i<t; i++)
        {
            if(aa[i]&&aa[t-i])//满足条件则跳出
            {
                puts("Yes");
                flag=1;
                break;
            }
        }
        if(flag==0)
            puts("No");
    }
    return 0;
}

C. Adidas vs Adivon

【解题思路】:

判断一下,在不断的对半切的过程中一直 /2,直到是一个奇数或者为0.统计次数。长和宽的次数相加。判断奇偶性就可以了。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;
int i,j,L,X,N;
bool flag;
int a[1005];
int aa[2100];
int main()
{
    int t,m,n;
    cin>>t;
    while(t--)
    {
        int sum=0;
        scanf("%d%d",&m,&n);
        while(m%2==0)
        {
            m=m/2;
            sum++;
        }
        while(n%2==0)
        {
            n=n/2;
            sum++;
        }
        if(sum%2!=0)
            printf("Adidas loses\n");
        else
            printf("Adivon prevails\n");
    }
    return 0;
}
F. Taiko taiko

【解题思路】一种情况是Y。一种情况是N,是Y的话,递推加1,是N的话,没分,a1=(a1+1)*p;b1+=a1;累加即可

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <map>
#include <set>
#include <string.h>
#include <algorithm>
using namespace std;
int i,j,L,X,N;
bool flag;
int a[1005];
int aa[2100];
int main()
{
    int t,n,m,i,j;
    double a1,b1,p;
    scanf("%d",&t);
    while(t--)
    {
        a1=b1=0;
        scanf("%d%lf",&n,&p);
        for(i=1;i<=n;i++){
            a1=(a1+1)*p;
            b1+=a1;
        }
        printf("%.6lf\n",b1);
    }
    return 0;
}
H. 硬币水题II

概率,,不解释。。

#include <stdio.h>
#include <string.h>
int main()
{
    int t;
    scanf("%d",&t);
    while (t--)
    {
        double n;
        scanf("%lf", &n);
        printf("%.2lf\n", 1/(n * (1 - n)));
    }
    return 0;
}

J. 鸣人的查克拉

【解题思路】:很有意思的一道题,简直考智商!

我的思路:最多发动2次,然后输入一个数,每次更新一下前一次的最大值,具体见代码了

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <map>
#include <set>
#include <string.h>
#include <algorithm>
using namespace std;
int Minn=-0x3f3f3f3f;
int main()
{
    int i,j,c,x,n,m;
    int a1,a2,a3,a4,a5;
    cin>>c>>n;
    a1=c;
    a2=a3=a4=a5=Minn;
    for(i=1; i<=n; i++)
    {
        cin>>x;
        if(a1>=x)
            a2=max(a2,a1-x); //9-9-9-9-9         /*第一步找消耗最小的,即剩余最大*/
        a3=max(a3,a2+x);     //10-11-12-12-14    /*第二步找下一次发动(也就是第一次发动)能增加最多的*/
        if(a3>=x)
            a4=max(a4,a3-x); //9-9-9-10-10      /*第三步找第二次发动消耗的最小的,剩余最大的
        a5=max(a5,a4+x);     //10-11-12-12-15   /*最后找最大的!*/
    }
    int res1=max(a3,a5);     //11-12-12-15
    int res2=max(a1,res1);   //11-12-12-15
    cout<<res2<<endl;//15!
}
/*
1  10-9  发动,变为9
2  9     不发动,9
3  12    结束1的时刻,加3 变为12
2  12-10 发动,为10
5  15    结束,加5为15!
*/

L斩

【解题思路】:

求直线与矩形交分割面积最小的那块面积的大小,计算几何,,共六种情况:

1:直线竖直穿过上下,形成两个梯形。

2:直线水平穿过左右,形成两个梯形。

3:穿过左边竖直和下边,形成一个三角形,一个五边形,求出三角形面积,最小一定是三角形面积,或者恰好形成两个三角形。

4:同3,穿过右边竖直和下边。

5:穿过左边和上边平行,同3。

6:穿过左边和下边平行,同5。

首先,利用矩形四条边和直线方程解出交点坐标,从而利用和已知坐标求出梯形,三角形面积(坐标相减,注意顺序),那如何判断形成了是哪个多边形?,注意到,梯形的话,上下交点一定在给定的两个坐标范围内,三角形的话,一定有个交点在矩形的直线上,如此一来,判断即可,最后比较,就可以求出面积了。

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
    int n,x1,y1,xr,yr,a,b,c;
    cin>>n;
    while(n--)
    {
        cin>>x1>>y1>>xr>>yr>>a>>b>>c;
        double s,S;
        double xy0=(c+b*y1)*1.0/-a;  //上下交,求出下交点
        double xy1=(c+b*yr)*1.0/-a;  //上下交,求出上交点
        double yx0=(c+a*x1)*1.0/-b;  //左右交,求出左交点
        double yx1=(c+a*xr)*1.0/-b;  //左右交,求出右交点
        bool t1=(xy0>=x1)&&(xy0<=xr);//判断边界,在下方
        bool t2=(xy1>=x1)&&(xy1<=xr);//判断边界,在上方
        bool t3=(yx0>=y1)&&(yx0<=yr);//判断边界,在左方
        bool t4=(yx1>=y1)&&(yx1<=yr);//判断边界,在右方
        if(t1&&t2)                   //直线在上下交
            s=(xy1+xy0-2*x1)*(yr-y1)/2.0;//梯形面积,
        else if(t3&&t4)             //直线在左右交
            s=(yx0+yx1-2*y1)*(xr-x1)/2.0;
        else if(t1&&t3)
            s=(yx0-y1)*(xy0-x1)/2.0;//三角形面积,
        else if(t1&&t4)
            s=(yx1-y1)*(xr-xy0)/2.0;
        else if(t2&&t3)
            s=(yr-yx0)*(xy1-x1)/2.0;
        else if(t2&&t4)
            s=(xr-xy1)*(yr-yx1)/2.0;
        S=fabs(xr-x1)*(yr-y1);
        s=min(s,S-s);
        printf("%.3lf\n",s);
    }
    return 0;
}



你可能感兴趣的:(ACM,比赛总结)