2016中北大学ACM程序设计新生赛题解

新生赛题目地址
a or an
输入字符串后判断第一个字符是不是’a’,’e’,’i’,’o’,’u’,即可。

#include<algorithm>
#include <iostream>
#include  <cstring>
#include   <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
const int MOD = 100000000;
int main()
{
    char a[100];
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%s",a);
            //判断首字符
            if(a[0]=='a'||a[0]=='e'||a[0]=='i'||a[0]=='o'||a[0]=='u')
            {
                printf("an\n");
            }
            else{
                printf("a\n");
            }
        }
    }
    return 0;
}

删数问题
枚举数字a[i],再判断数字a[i]是不是在a[i,i+s]中最小,如果不是就删除,每删除一个就使s减1,直到s等于0,或剩余的数量小于总长度,那么剩下的数字都要比前面的数字大,全部删除。

#include<algorithm>
#include <iostream>
#include  <cstring>
#include   <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
const int MOD = 1000000007;
typedef long long ll;
using namespace std;
char a[1000];
int vis[1000];
int s;
int main()
{
    while(scanf("%s",a)!=EOF)
    {
        scanf("%d",&s);
        bool flag=false;
        memset(vis,-1,sizeof(vis));
        int len=strlen(a);
        int h0=0;
        for(int i=0;i<len;i++)//记录数组中0的个数,如果大于s就直接输出0
        {
            if(a[i]=='0')
            {
                h0++;
            }
        }
        if(s>=len-h0)
        {
            printf("0\n");
            continue;
        }
        for(int i=0; i<len; i++)
        {
            int t=0;
            for(int j=1;j<=s;j++)
            {
                if(a[i]>a[i+j])
                {
                    vis[i]=0;
                    s--;
                    break;
                }
            }
            if(i+s+1>len)//剩余的数量小于总长度,那么剩下的数字都要比前面的数字大,全部删除。
            {
                len-=s;
                break;
            }
            if(!s)//已经删除完毕
            {
                break;
            }
        }
        bool flag1=false;
        for(int i=0; i<len; i++)
        {
            if(!flag1&&a[i]=='0')//跳过前导0
            {
                continue;
            }
            if(vis[i])
            {
                flag1=true;
                printf("%c",a[i]);
            }
        }
        if(!flag1)全部都是0时输出0
        {
            printf("0");
        }
        printf("\n");
    }
    return 0;
}

潜入密室
找到通项公式f[i]=f[i-1]+3*i-1。先打出表,在二分搜索。或是找到其他公式直接计算出来也可以。

#include<algorithm>
#include <iostream>
#include  <cstring>
#include   <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
const int MOD = 100000000;
long long n;
long long a[900005];
int main()
{
    long long ans=0;
    a[0]=0;
    for(int i=1;i<=900000;i++)
    {
        ans+=i*3-1;
        a[i]=ans;
    }
    while(scanf("%lld",&n)!=EOF)
    {
        int l=0,r=900000,mid,t=100;
        while(t--)
        {
            mid=(l+r)/2;
            if(a[mid]<=n&&n<a[mid+1])
            {
                ans=mid;
                break;
            }
            if(a[mid]>n)
            {
                r=mid;
            }
            else
            {
                l=mid;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

开锁
先判断字符串是不是回文,如果是,不管之后数值如何,它都是回文。如果不是,就从数组两端分析如果每一个正串都对应的是一串逆序串就表明组合后是回文。

#include<algorithm>
#include <iostream>
#include  <cstring>
#include   <cstdio>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
const int MOD = 100000000;
char a[1000005];
int b[1000005];
int main()
{
    int n;
    while(scanf("%s",a)!=EOF)
    {
        bool flag=true;
        int len=strlen(a);
        for(int i=0;i<len/2;i++)
        {
            if(a[i]!=a[len-i-1])
            {
                flag=false;
            }
        }
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
        }
        if(flag)
        {
            printf("YES\n");
        }
        else
        {
            flag=true;
            int l=0,r=n-1;
            while(true)
            {
                if(l>r)
                {
                    break;
                }
                if(b[l]*b[r]>0)
                {
                    flag=false;
                    break;
                }
                if(abs(b[l])==abs(b[r]))
                {
                    r--;
                    l++;
                }
                else if(abs(b[l])>abs(b[r]))
                {
                    b[l]+=b[r];
                    r--;
                }
                else if(abs(b[l])<abs(b[r]))
                {
                    b[r]+=b[l];
                    l++;
                }
            }
            if(flag)
            {
                printf("YES\n");
            }
            else
            {
                printf("NO\n");
            }
        }
    }
    return 0;
}

偷宝记
枚举每个左端点值的情况,把在a[i].x到a[i].x+x的所有y值放入数组再排序,最后尺取出最优解。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
struct node
{
    int x, y;
};
bool cmp(node a, node b)
{
    return a.x<b.x;
}
int n, x, y;
node a[1005];
int findd(int x, int y)
{
    int maxn = 0;
    int b[1005];
    for (int i = 0, l = 0; i<n; i++)
    {
        if (a[i].x == a[l].x && i != l)
        {
            continue;
        }
        else
        {
            l = i;
        }
        int cnt = 0;
        for (int j = l; j<n; j++)
        {
            if (a[i].x + x<a[j].x)
            {
                break;
            }
            b[cnt++] = a[j].y;
        }

        sort(b, b + cnt);

        for (int j = 0, k = 0; j<cnt; j++)
        {
            while (k < cnt && b[j] + y >= b[k])
            {
                k++;
            }
            maxn = max(maxn, k - j);
        }
    }
    return maxn;
}
int main()
{
    while (cin >> n >> x >> y)
    {
        for (int i = 0; i<n; i++)
        {
            cin >> a[i].x >> a[i].y;
        }
        sort(a, a + n, cmp);
        int ans = findd(x, y);
        printf("%d\n", ans);
    }
    return 0;
}

密室逃脱
先按从上到下从左到右的顺序把板子排序,保存第一步后的两种情况。枚举板子,有以下种情况:

1.到达一层。
2.队列的点在板子左侧。
3.点在板子上方。
4.点在板子右侧。
5.点用完了。
6.点不是在板子上一行的。
7.点和板子同行。

对应不同情况进行处理。
也可以如代码2的方法处理:
从最高行开始枚举,判断有没有可达情况在上方,有的话判断该点位置是不是在板子上,分别处理。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
struct node
{
    int h, r, l;
    bool operator < (const node &t1) const
    {
        if (h != t1.h)
        {
            return h>t1.h;
        }
        else
        {
            return r<t1.r;
        }
    }
}no[1000005];
struct step
{
    int h;
    int x;
    int s;
}ne, nel, ner;
int vis[1000005][2];
queue<step>q;
int n, h;
void reb(step s)
{
    if (s.s == INF)
    {
        return;
    }
    if (vis[s.x][0] != s.h)
    {
        vis[s.x][0] = s.h;
        vis[s.x][1] = s.s;
        q.push(s);
    }
}
int findd()
{
    int t = 0, i = 0;
    while(no[i].h == h)
    {
        i++;
    }
    nel.h = no[i].h;
    nel.x = no[i].l;
    nel.s = INF;
    ner.h = no[i].h;
    ner.x = no[i].r;
    ner.s = INF;
    while (!q.empty())
    {
        ne = q.front();
        if (ne.h == 1)
        {
            ne.s++;
            ne.h--;
            vis[ne.x][0] = ne.h;
            vis[ne.x][1] = ne.s;
        }
        else if (i >= n || ne.h>no[i].h + 1 || ne.x<no[i].l)
        {
            ne.s++;
            ne.h--;
            reb(ne);
        }
        else if (no[i].l <= ne.x&&ne.x <= no[i].r)
        {
            nel.s = min(nel.s, ne.x - no[i].l + 1 + ne.s);
            ner.s = min(ner.s, no[i].r - ne.x + 1 + ne.s);
        }
        else
        {
            reb(ner);
            reb(nel);
            i++;
            nel.h = no[i].h;
            nel.x = no[i].l;
            nel.s = INF;
            ner.h = no[i].h;
            ner.x = no[i].r;
            ner.s = INF;
            continue;
        }
        q.pop();
        if (q.empty()&&nel.x!=INF)
        {
            reb(ner);
            reb(nel);
            i++;
            nel.h = no[i].h;
            nel.x = no[i].l;
            nel.s = INF;
            ner.h = no[i].h;
            ner.x = no[i].r;
            ner.s = INF;
        }
    }
    int minn = INF;
    for (int i = 0; i<1000005; i++)
    {
        if (vis[i][0] == 0)
            minn = min(vis[i][1], minn);
    }
    return minn;
}
int main()
{
    while (cin >> n)
    {
        while (!q.empty())
        {
            q.pop();
        }
        h = 0;
        memset(vis, -1, sizeof(vis));
        for (int i = 0, a, b, c; i<n; i++)
        {
            cin >> b >> a >>c;
            no[i].h = a;
            no[i].l = b;
            no[i].r = b + c;
            h = max(h, a);
        }
        sort(no, no + n);
        ne.s = 0;
        ne.h = no[0].h;
        ne.x = no[0].l;
        q.push(ne);
        ne.s = no[0].r - no[0].l;
        ne.h = no[0].h;
        ne.x = no[0].r;
        q.push(ne);
        vis[no[0].l][0] = h;
        vis[no[0].l][1] = 0;
        vis[no[0].r][0] = h;
        vis[no[0].r][1] = no[0].r - no[0].l;
        printf("%d\n", findd());
    }
    return 0;
}

代码2

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int dp[1005][2005];
int vis[1005][2005][3];
int n,h;
int findd()
{
    while(h)
    {
        h--;
        for(int i=0; i<=2000; i++)
        {
            if(dp[h+1][i]!=-1)
            {
                if(vis[h][i][0]==0)
                {
                    dp[h][i]=dp[h+1][i]+1;
                }
                else
                {
                    if(dp[h][vis[h][i][1]]==-1)
                    {
                        dp[h][vis[h][i][1]]=i-vis[h][i][1]+dp[h+1][i]+1;
                        dp[h][vis[h][i][2]]=vis[h][i][2]-i+dp[h+1][i]+1;
                    }
                    else
                    {
                        dp[h][vis[h][i][1]]=min(i-vis[h][i][1]+dp[h+1][i]+1,dp[h][vis[h][i][1]]);
                        dp[h][vis[h][i][2]]=min(vis[h][i][2]-i+dp[h+1][i]+1,dp[h][vis[h][i][2]]);
                    }
                }
            }
        }
    }
    int minn=INF;
    for(int i=0; i<=2000; i++)
    {
        if(dp[0][i]!=-1)
            minn=min(minn,dp[0][i]);
    }
    return minn;
}
void inid()
{
    for(int i=0; i<=2000; i++)
    {
        if(vis[h][i][0])
        {
            dp[h][vis[h][i][1]]=0;
            dp[h][vis[h][i][2]]=vis[h][i][2]-vis[h][i][1];
            return;
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        h=0;
        memset(vis,0,sizeof(vis));
        memset(dp,-1,sizeof(dp));
        for(int i=0,a,b,c; i<n; i++)
        {
            scanf("%d%d%d",&b,&a,&c);
            if(a==0)
            {
                continue;
            }
            for(int i=0; i<=c; i++)
            {
                vis[a][b+i][0]=1;
                vis[a][b+i][1]=b;
                vis[a][b+i][2]=b+c;
            }
            h=max(h,a);
        }
        inid();
        printf("%d\n",findd());
    }
    return 0;
}

郭姐分石子
有n个石子每次分出i个石子,使每次分出的石子大于等于上次分出的石子,最后递归查找。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int findd(int n,int m,int k)
{
    int ans=0;
    if(m==0)
    {
        if(n==0)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
    for(int i=k;i<=n;i++)
    {
        ans+=findd(n-i,m-1,i);
    }
    return ans;
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        printf("%d\n",findd(n,m,1));
    }
    return 0;
}

笨 笨
简单的排序。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int main()
{
    char a[10];
    while(scanf("%s",a)!=EOF)
    {
        sort(a,a+3);
        printf("%s\n",a);
    }
    return 0;
}

非洲来的郭姐
用错排公式求解,第i点放的情况有n-1种,同时有恰好这点放的值的位置放上i,和其他情况。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int findd(int n)
{
    if(n<0)
    {
        return 0;
    }
    if(n==0)
    {
        return 1;
    }
    return (n-1)*(findd(n-2)+findd(n-1));
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        printf("%d\n",findd(n)+1);
    }
    return 0;
}

五子棋
枚举每个点的情况看看按一个方向搜过去能否有五子连珠的情况。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
char mapp[200][200];
int D[4][2]={{1,1},{0,1},{-1,1},{1,0}};
int n,m,T;
bool check(char a,int x,int y)
{
    for(int i=0;i<4;i++)
    {
        if(0>x+D[i][0]*4||x+D[i][0]*4>=n||0>y+D[i][1]*4||y+D[i][1]*4>=m)
        {
            continue;
        }
        bool flag=true;
        for(int j=0;j<5;j++)
        {
            if(a!=mapp[x+D[i][0]*j][y+D[i][1]*j])
            {
                flag=false;
                break;
            }
        }
        if(flag)
        {
            return true;
        }
    }
    return false;
}
char findd()
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<m;j++)
        {
            if(mapp[i][j]!='X')
            {
                if(check(mapp[i][j],i,j))
                {
                    return mapp[i][j];
                }
            }
        }
    }
    return 'A';
}
int main()
{
    while(scanf("%d",&T)!=EOF)
    {
        for(int t=1;t<=T;t++)
        {
            scanf("%d%d",&n,&m);
            for(int i=0;i<n;i++)
            {
                getchar();
                scanf("%s",mapp[i]);
            }
            printf("Case %d:%c\n",t,findd());
        }
    }
    return 0;
}

森林
假设怪物到出口的距离小于等于人过去的距离则必定相遇,如果大于则必定不相遇。所以从出口反向bfs即可。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
char mapp[1000][1000];
int vis[1000][1000];
int n,m;
int D[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
struct node
{
    int x,y;
    int step;
} e,ne;
queue<node>q;
int maxn;
int bfs()
{
    maxn=INF;
    int ans=0;
    while(!q.empty())
    {
        q.pop();
    }
    q.push(e);
    memset(vis,-1,sizeof(vis));
    vis[e.x][e.y]=0;
    while(!q.empty())
    {
        if(q.front().step<maxn)
        {
            for(int i=0; i<4; i++)
            {
                int x=q.front().x+D[i][0];
                int y=q.front().y+D[i][1];
                int step=q.front().step+1;
                if(0<=x&&x<n&&0<=y&&y<m&&vis[x][y]&&mapp[x][y]!='T')
                {
                    if(mapp[x][y]=='S')
                    {
                        maxn=step;
                    }
                    else
                    {
                        ans+=mapp[x][y]-'0';
                    }
                    ne.x=x;
                    ne.y=y;
                    ne.step=step;
                    vis[x][y]=0;
                    q.push(ne);
                }
            }
        }
        q.pop();
    }
    return ans;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=0; i<n; i++)
        {
            scanf("%s",mapp[i]);
        }
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                if(mapp[i][j]=='E')
                {
                    e.x=i;
                    e.y=j;
                    e.step=0;
                }
            }
        }
        printf("%d\n",bfs());
    }
    return 0;
}

图像旋转
输入后输出。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int main()
{
    int a[105][105];
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=0; i<m; i++)
        {
            for(int j=n-1; j>=0; j--)
            {
                printf(j?"%d ":"%d\n",a[j][i]);
            }
        }
    }
    return 0;
}

连续出现的字符
遍历字符计算连续出现的长度。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int n, m;
char a[1000];
int main()
{
    while (cin >> n)
    {
        cin >> a;
        int len = strlen(a);
        int l = 0;
        bool flag = false;
        for (int i = 0; i<=len;)
        {
            if (a[i] == a[l])
            {
                i++;
            }
            else
            {
                if (i - l >= n)
                {
                    flag = true;
                    break;
                }
                else
                {
                    l = i;
                }
            }
        }
        if (flag)
        {
            printf("%c\n", a[l]);
        }
        else
        {
            printf("No\n");
        }
    }
    return 0;
}

正方形面积
输入后输出平方。

#include<algorithm>
#include <iostream>
#include  <ctype.h>
#include  <cstring>
#include  <fstream>
#include   <cstdio>
#include   <vector>
#include   <string>
#include    <cmath>
#include    <stack>
#include    <queue>
#include      <set>
#include      <map>
#define INF (1<<30)
#define PI acos(-1.0)
typedef long long ll;
using namespace std;
int n;
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        printf("%d\n",n*n);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lxworld123/article/details/53817075
今日推荐