2015 Syrian Private Universities Collegiate Programming Contest

五迷三道 提交于 2019-11-27 16:43:53

题目

A题(好吧他加载不出来)
B题

把给的一个n*m的矩形切成一个个小方格,需要切n*m-1次,切奇数次是先手赢,偶数次先手输。
#include <stdio.h>
#define ll long long
int main()
{
    int T,a,b;
    ll z;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&a,&b);
        z=a*b;
        if((z-1)%2==0) printf("Hussain\n");
        else printf("Hasan\n");
    }
    return 0;
}

C题

给出n个矩形的坐标,(i,0)左下,(j,k)右上,求矩形面积。
数据量小,暴力搜索给出坐标内的矩形有没有遍历过。
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
    int i,j,n,sum,t;
    int x,y,z;
    int vis[105][105];
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n;
        memset(vis,0,sizeof(vis));
        sum=0;
        while(n--)
        {
            cin>>x>>y>>z;
            for(i=0;i<z;i++)
            {
                for(j=x;j<y;j++)
                {
                    if(vis[i][j]==0)
                    {
                        sum++;
                        vis[i][j]=1;
                    }
 
                }
            }
        }
        cout<<sum<<endl;
    }
    return 0;
}

D题

问序列的最大长度,满足a[i]=a[i-1]+1;
经典dp。
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
    int dp[20010];
    int i,t,n,x;
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n;
        int ans=0;
        memset(dp,0,sizeof(dp));
        for(i=1;i<=n;i++)
        {
            cin>>x;
            dp[x]=dp[x-1]+1;
            ans=max(ans,dp[x]);
        }
        cout<<ans<<endl;
    }
    return 0;
}
对了,在这里了解到用cin读入大数没有scanf用时快(用cinTL,用scanfAC)。在用cin读入大数时,可以加上
ios::sync_with_stdio(false),效率高些。

E题

   题目里都是看不懂的词,后来才知道前面全是没用的,问题跟前面完全没关系,就后面一句话有用。
 题意: 给出两个点坐标,求从一个点到另一个点能不能到(只能斜着走),能到输出最短步数,不能输出“can’t reach!”
    
 思路: 这两个点的横、纵坐标之差如果同奇偶性,可达,非同奇偶,不可达(画画图)。
    #include<bits/stdc++.h>
    #include <iostream>
    using namespace std;
    int main()
    {
        int t,n,x,y,a,b;
        cin>>t>>n;
        while(t--)
        {
            cin>>x>>y>>a>>b;
            x=abs(x-a);
            y=abs(y-b);
            if(x%2==0&&y%2==0||x%2!=0&&y%2!=0)
            {
                int ans=max(x,y);
                cout<<ans<<endl;
            }
            else
                cout<<"can't reach!"<<endl;
        }
        return 0;
    }

F题

题意:给出一个有n个数的序列,表示解决第i个题需要的用时ai,问300秒内队伍能解决的最多题目和最少罚时(罚时等于解决这道题的当前时间。例如,做完第一道题用时6s(罚时为6s),第二道题用时31s,(罚时为6+31=37s))
思路:排序,不超过300s内做题数量。
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
    int i,k,n,ans,t;
    int a[150];
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+1+n);
        ans=0;
        k=0;
        for(i=1;i<=n;i++)
        {
            if(ans+a[i]<=300)
            {
                ans+=a[i];
                k++;
            }
            else
            {
                break;
            }
        }
        ans=0;
        for(i=1;i<=k;i++)
        {
            ans+=(k-i+1)*a[i];
        }
        cout<<k<<' '<<ans<<endl;
    }
   return 0;
}

G题

题意:看给的字符数组里(水平、竖直、斜向都可以)有没有“pie”,
思路:搜索
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
    int i,j,n,m,t;
    int flag;
    char s[25][25];
    ios::sync_with_stdio(false);
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                cin>>s[i][j];
            }
        }
        flag=0;
        for(i=0;i<n;i++)
        {
            for(j=0;j<m;j++)
            {
                if(s[i][j]=='p')
                {
                    if(i+2<n)
                    {
                        if(s[i+1][j]=='i'&&s[i+2][j]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(i-2>=0)
                    {
                        if(s[i-1][j]=='i'&&s[i-2][j]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(j+2<m)
                    {
                        if(s[i][j+1]=='i'&&s[i][j+2]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(j-2>=0)
                    {
                        if(s[i][j-1]=='i'&&s[i][j-2]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(i+2<n&&j+2<m)
                    {
                         if(s[i+1][j+1]=='i'&&s[i+2][j+2]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(i-2>=0&&j-2>=0)
                    {
                         if(s[i-1][j-1]=='i'&&s[i-2][j-2]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(i-2>=0&&j+2<m)
                    {
                         if(s[i-1][j+1]=='i'&&s[i-2][j+2]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                    if(i+2<n&&j-2>=0)
                    {
                        if(s[i+1][j-1]=='i'&&s[i+2][j-2]=='e')
                        {
                            flag=1;
                            break;
                        }
                    }
                }
            }
        }
        if(flag)
            cout<<"Cutie Pie!"<<endl;
        else
            cout<<"Sorry Man"<<endl;
    }
    return 0;
}

H题

题意:给出n个房子,m条路,k个人,求从1到n且要经过k个人的房子的最短路程。
思路:最短路。先用floyd求出每个房子间的最短距离,再从1出发,分别到k个房子,再到n(从1到k到n,k个房子全排列,每种顺序都走一遍,维护最小值)
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int mmap[110][110];
const int inf=0x3f3f3f3f;
int n;
void init()
{
    int i,j;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=n;j++)
        {
            if(i==j)
                mmap[i][i]=0;
            else
                mmap[i][j]=inf;
        }
    }
}
void floyd()
{
    int i,j,k;
    for(k=1;k<=n;k++)
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(mmap[i][j]>mmap[i][k]+mmap[k][j])
                    mmap[i][j]=mmap[i][k]+mmap[k][j];
            }
        }
    }
}
int main()
{
    int t,m,u,v,w,i,k,sum,kk,ans,T;
    int a[10];
    cin>>T;
    for(t=1;t<=T;t++)
    {
        cin>>n>>m>>k;
        init();
        while(m--)
        {
            cin>>u>>v>>w;
            if(w<mmap[u][v])
                mmap[u][v]=mmap[v][u]=w;
        }
        for(i=1;i<=k;i++)
        {
            cin>>a[i];
        }
        floyd();
        sort(a+1,a+1+k);
        ans=inf;
        do{
           sum=mmap[1][a[1]];
           kk=a[1];
           for(i=2;i<=k;i++)
            {
                sum+=mmap[kk][a[i]];
                kk=a[i];
            }
            sum+=mmap[kk][n];
            ans=min(ans,sum);
        }while(next_permutation(a+1,a+1+k));
        cout<<"Case "<<t<<": "<<ans<<endl;
    }
    return 0;
}
这里新学到了全排列函数,next_permutation(start,end,cmp),三个参数分别是数组开始地址,结束地址,排序方式。

next_permutation详解
I题

  题意:给出一个字符串,问能不能改成回文串。
    思路:出现奇数次的字符如果只有一种,可以改成回文串。在输出的时候对于(i=97;i<=122;i++)正输出一遍,再输出奇数个的字符,最后反输出一遍。
    #include<bits/stdc++.h>
    #include <iostream>
    using namespace std;
    int main()
    {
        char s[1005];
        int t,n,i,j,k;
        int a[210];
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s",s);
            n=strlen(s);
            memset(a,0,sizeof(a));
            for(i=0; i<n; i++)
            {
                k=(int)s[i];
                a[k]++;
            }
            int c,flag;
            flag=0;
            for(i=97; i<=122; i++)
            {
                if(a[i]%2!=0)
                {
                    if(!flag)
                    {
                        c=i;
                        flag=1;
                    }
                    else
                        break;
                }
            }
            if(i<=122)
                cout<<"impossible"<<endl;
            else
            {
                for(i=97; i<=122; i++)
                {
                    if(a[i])
                    {
                        for(j=1; j<=a[i]/2; j++)
                        {
                            printf("%c",i);
                        }
                    }
                }
                if(flag) printf("%c",c);
                for(i=122; i>=97; i--)
                {
                    if(a[i])
                    {
                        for(j=1; j<=a[i]/2; j++)
                        {
                            printf("%c",i);
                        }
                    }
                }
                printf("\n");
            }
        }
        return 0;
    }

J题

题意:给金额为x和y的两个货币,问能不能通过交换出现所有金额。
思路:只要出现1,就一定能出现所有金额。
找是不是__gcd(x,y)=1。
#include<bits/stdc++.h>
#include <iostream>
using namespace std;
int main()
{
    int t,n,m,k;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        if(n<m)
        {
            k=n;
            n=m;
            m=k;
        }
        if(__gcd(n,m)==1)
            cout<<"GOOD"<<endl;
        else
            cout<<"NOT GOOD"<<endl;
    }
return 0;
}

K题

QWQ
QAQ
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!