浙江省10th程序设计竞赛部分题解

A题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3705

第一行给出一个数字,代表样例的个数

第二行给出两个数n和m,代表人数和需要选出的排名的前m个人

第三四行分别给出MaoMao Selection和Surgeon Contest的题目数量与题号

第五行给出拿到前三等奖的数目,接下来给出每个获奖的队伍和获得的排名

最后给出每个人的信息,包括人名,队名,性别,OJ里的做题数,参加比赛的数目

然后给出题号与比赛的得分

而每个人的得分计算是这样:

首先是做的题所得的分:1.在MaoMao Selection做的题得2.5分

                               2.在Surgeon Contest做的题得1.5分

                                3.如果不在这两个地方做的题并且题号为素数,得1分

                                4.否则0.3分

如果所在的队伍得奖了:一等奖36分,二等27,三等18

如果是女的:加33分

如果参加过比赛,则取第三高的分数,计算公式Pts = max(0, (r - 1200) / 100) * 1.5为得分,如果小于3次比赛则不算

题意理清楚了之后,按照题目的叙述模拟即可。

#include <iostream>
#include <string>
#include <stdio.h>
#include <algorithm>
#include <iomanip>
#include <map>
#include <cmath>
using namespace std;
#define INF 1e-3
int t;
int n,m,r,s,q,pri,p,c,index;
int inS[505],old[505],rating[1005];
char sex;
map<string,int> team;
struct node
{
    string name;
    double rat;
};
node str[505];
string S,temp;
bool prime(int x)
{
    if(x<=1)
    return false;
    if(x==2)
    return true;
    if(x%2==0)
    return false;
    for(int i=3;i<=x/2;i+=2)
    {
        if(x%i==0)
        return false;
    }
    return true;
}
bool cmp(node a,node b)
{
    if(fabs(a.rat-b.rat)<INF)
    return a.name<b.name;
    return a.rat>b.rat;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        team.clear();
        scanf("%d%d",&n,&m);
        scanf("%d",&r);
        for(int i=0;i<r;++i)
        scanf("%d",inS+i);
        sort(inS,inS+r);
        scanf("%d",&s);
        for(int i=0;i<s;++i)
        scanf("%d",old+i);
        sort(old,old+s);
        scanf("%d",&q);
        for(int i=1;i<=q;++i)
        {
            cin>>S>>pri;
            if(pri>=1&&pri<=3)
            team[S]=pri; 
        }
        for(int i=0;i<n;++i)
        {
            cin>>S>>temp>>sex;
            str[i].name=S;
            str[i].rat=0.0;
            if(team[temp])
            {
                str[i].rat+=(5-team[temp])*9.0;
            }
            if(sex=='F')
            str[i].rat+=33.0;
            cin>>p>>c;
            for(int j=0;j<p;++j)
            {
                scanf("%d",&index);
                if(binary_search(inS,inS+r,index))
                    str[i].rat+=2.5;
                else if(binary_search(old,old+s,index))
                str[i].rat+=1.5;
                else if(prime(index))
                str[i].rat+=1.0;
                else 
                str[i].rat+=0.3;
            }
            for(int j=0;j<c;++j)
            {
                scanf("%d",rating+j);
            }
            if(c>=3)
            {
                sort(rating,rating+c);
                str[i].rat+=max(0.0,(rating[c-3]-1200.0)*1.0/100)*1.5;
            }
    
        }
        sort(str,str+n,cmp);
        for(int j=0;j<m;++j)
        {
            cout<<str[j].name<<' '<<setiosflags(ios::fixed)<<setprecision(3)<<str[j].rat<<endl;
        }
    }
    return 0;
}

B题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3706

题意:给你两个砝码。你可以把其中一个砝码拆分成两个。问你用拆分后的砝码最多可以组合出多少重量。

水题,暴力枚举组合,用set排序去重,注意最后处理为0的情况。

#include <iostream>
#include <cstdio>
#include <set>
#include <cmath>
#include <algorithm>
using namespace std;
int cal(int a,int b,int c)
{
    set <int> cnt;
    cnt.insert(abs(a));
    cnt.insert(abs(b));
    cnt.insert(abs(c));
    cnt.insert(abs(a+b));
    cnt.insert(abs(a+c));
    cnt.insert(abs(b+c));
    cnt.insert(abs(a-b));
    cnt.insert(abs(a-c));
    cnt.insert(abs(b-c));
    cnt.insert(abs(a+b+c));
    cnt.insert(abs(a+b-c));
    cnt.insert(abs(a+c-b));
    cnt.insert(abs(b+c-a));
    cnt.erase(0);
    return cnt.size();
}
int main()
{
    int t,a,b,maxx;
    scanf("%d",&t);
    while(t--)
    {
        maxx=0;
        scanf("%d%d",&a,&b);
        for(int i=1;i<=a/2;i++)
        {
            maxx=max(cal(i,a-i,b),maxx);
        }
        for(int i=1;i<=b/2;i++)
        {
            maxx=max(cal(i,b-i,a),maxx);
        }
        printf("%d
",maxx);
    }
    return 0;
}

D题 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3708

题意:水题。公交路线的数量/公交车的数量,注意两点之间存在多条路线的话,只能算是一条。构图即可。

#include<iostream>
#include<string>
#include<iomanip>
#include<cstring>
using namespace std;
int a[505],b[505];
int  map[505][505];
int main()
{
    int T,bus,m;
    cin>>T;
    while(T--)
    {
        cin>>bus>>m;
        memset(map,0,sizeof(map));
        int sum=0;
        for(int i=1;i<=m;i++)
        {
            cin>>a[i];
        }
        for(int i=1;i<=m;i++)
        {
            cin>>b[i];
        }
        for(int i=1;i<=m;i++)
        {
            if(map[a[i]][b[i]]||map[b[i]][a[i]])
            continue;
            else
            {
                map[a[i]][b[i]]=1;
             sum++;
           }
        }
        double ans;
        ans=sum*1.0/(bus*1.0);
        cout<<fixed<<setprecision(3)<<ans<<endl;
    }
    
}

F题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3710

题意是给你n个人,m对朋友关系,如果两个人的公共好友超过k人,那他们可以成为新的朋友,问经过一段“”足够长的时间后“, 新产生了多少对朋友关系?

数据量比较小。暴力即可。遍历每对关系,如果他们之间的好友超过k,就将他们置为好友,然后从头继续扫描。一旦没有新的关系产生,结束,输出结果。

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
bool map[105][105];
bool vis[105],flags;
int k,t,n,m,u,v;
int sum,cnt;
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        cnt=0;
        scanf("%d%d%d",&n,&m,&k);
        memset(map,0,sizeof(map));
        for(int i=0;i<n;++i)
        {
            map[i][i]=1;
        }
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d",&u,&v);
            map[u][v]=1;
            map[v][u]=1;
        }
        while(true)
        {
            flags=false;
            for(int i=0;i<n;++i)
            {
                for(int j=0;j<n;++j)
                {
                    if(map[i][j])
                    continue;
                    sum=0;
                    for(int ll=0;ll<n;++ll)
                    {
                        if(map[i][ll]&&map[ll][j])//求每对关系是不是满足>=4的时候,枚举中间点
                        {
                            sum++;
                            //cout<<i<<' '<<j<<' '<<ll<<endl;
                            if(sum>=k)
                            break;
                        }
                    }
                    if(sum>=k)
                    {
                        map[i][j]=1;
                        map[j][i]=1;
                        flags=true;
                        cnt++;
                    }
                }
            }
            if(!flags)
            break;
        }
        printf("%d
",cnt);
    }
    return 0;
}

H:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3712

水题,按照规则计分即可。贪心。

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int main()
{
    int a,b,c;
    int T;
    cin>>T;
    while(T--)
    {
        cin>>a>>b>>c;
        int max1=0,min1=0;
        int i=1;
        for(;i<=a;i++)
        {
            min1+=300*((i-1)*2+1);
        }
        for(;i<=a+b;i++)
        {
            min1+=100*((i-1)*2+1);
        }
        for(;i<=a+b+c;i++)
        {
            min1+=50*((i-1)*2+1);
        }
        
        for(int i=1;i<=c;i++)
        {
            max1+=50*((i-1)*2+1);
        }
        for(int j=c+1;j<=c+b;j++)
        {
            max1+=100*((j-1)*2+1);
        }
        for(int i=c+b+1;i<=a+b+c;i++)
        {
            max1+=300*((i-1)*2+1);
        }
        
        cout<<min1<<" "<<max1<<endl;
    }
    return 0;
}

I:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3713

坑爹的题意。很难理解啊。输入的字符串中空格也要算到长度里面,先将串的长度换成二进制,取后七位(&127即1111111),然后如果前面还有1的话(没有的话就是0),再加一位最高位1(| 128即可),这样组成一个字节8位,依次循环。  处理完长度之后,将字符串的内容每一个字符的ASCII码按照十六进制输出即可。注意,空串的时候输出00。

#include<iostream>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int n;
    cin>>n;
    getchar();
    while(n--)
    {
        string s;
        getline(cin,s);
        int len=s.length();
        if(len==0)
        {
            cout<<"00";
        }
        else
        {
        int temp=len;
        int cur=0;
        while(temp)
        {
            cur=temp&127;
            temp=temp>>7;
            if(temp)
            cur|=128;
            printf("%02X",cur);
        }
        
        for(int i=0;i<len;i++)
        {
            int op=s[i];
            printf("%02X",op);//控制输出位数,不足的话前面补0,X代表大写的十六进制
        }
        
        }
        cout<<endl;
    }
    return 0;    
}

J:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3714

水题。在环形中取连续m个数的最大值,将数组复制加入后面相当于处理环形。

#include<iostream>
#include<string>
using namespace std;
int s[1000];
int main()
{
    int T,n,m;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        {
         cin>>s[i];
         s[i+n]=s[i];
        }
        int max1=-1;
        for(int i=1;i<=2*n-m;i++)
        {
            int sum=0;
            for(int j=i;j<i+m;j++)
            {
                sum+=s[j];
            }
            if(sum>max1)
            max1=sum;
        }
        cout<<max1<<endl;
    }
    return 0;
}

K:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3715

等待更新。。。

原文地址:https://www.cnblogs.com/Tach-ac/p/4396973.html