CCF 2015 真题 持续更新

8 篇文章 0 订阅

消除类游戏

描述

问题描述
  消除类游戏是深受大众欢迎的一种游戏,游戏在一个包含有n行m列的游戏棋盘上进行,棋盘的每一行每一列的方格上放着一个有颜色的棋子,当一行或一列上有连续三个或更多的相同颜色的棋子时,这些棋子都被消除。当有多处可以被消除时,这些地方的棋子将同时被消除。
  现在给你一个n行m列的棋盘,棋盘中的每一个方格上有一个棋子,请给出经过一次消除后的棋盘。
  请注意:一个棋子可能在某一行和某一列同时被消除。
输入格式
  输入的第一行包含两个整数n, m,用空格分隔,分别表示棋盘的行数和列数。
  接下来n行,每行m个整数,用空格分隔,分别表示每一个方格中的棋子的颜色。颜色使用1至9编号。
输出格式
  输出n行,每行m个整数,相邻的整数之间使用一个空格分隔,表示经过一次消除后的棋盘。如果一个方格中的棋子被消除,则对应的方格输出0,否则输出棋子的颜色编号。
样例输入
4 5
2 2 3 1 2
3 4 5 1 4
2 3 2 1 3
2 2 2 4 4
样例输出
2 2 3 0 2
3 4 5 0 4
2 3 2 0 3
0 0 0 4 4
样例说明
  棋盘中第4列的1和第4行的2可以被消除,其他的方格中的棋子均保留。
样例输入
4 5
2 2 3 1 2
3 1 1 1 1
2 3 2 1 3
2 2 3 3 3
样例输出
2 2 3 0 2
3 0 0 0 0
2 3 2 0 3
2 2 0 0 0
样例说明
  棋盘中所有的1以及最后一行的3可以被同时消除,其他的方格中的棋子均保留。
评测用例规模与约定
  所有的评测用例满足:1 ≤ n, m ≤ 30。

分析

挺迷的,一开始总是30分,不知道改了哪里,突然就过了……
听上去很麻烦,但是CCF的题,只要数据量不大,那完全就可以按照最符合直觉的思路来
就遍历就好了,每次查看是不是有三个相同。什么?三个以上?只要迭代是加一的,三个三个的总能全部找到的
只需要用另一个数组来专门负责标记就好了,这样也不怕重复标记

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
int chess[32][32];
int ans[32][32];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i = 0;i<n;i++)
        for(int j=0;j<m;j++)
        {
            scanf("%d",&chess[i][j]);
            ans[i][j] = chess[i][j];
        }

        int i=0 ,j = 0;
        for( i =0; i<n;i++)
        {
            for(j = 0;j<m;j++)
            {
                if(j+1<m && j+2<m)
                {
                    if(chess[i][j]==chess[i][j+1] && chess[i][j+2]==chess[i][j])
                       {
                        ans[i][j]=0;
                        ans[i][j+1]=0;
                        ans[i][j+2] = 0;
                       }
                }
                if(i+1<n && i+2 <n)
                {
                    if(chess[i][j]==chess[i+1][j]&& chess[i+2][j]==chess[i][j])
                    {
                        ans[i][j]=0;
                        ans[i+1][j]=0;
                        ans[i+2][j]=0;
                    }
                }
            }
        }
        for(int i = 0;i<n;i++)
        {
            for(int j = 0;j<m;j++)
            {
                printf("%d ",ans[i][j]);
            }
            printf("\n");
        }


    }
}

日期计算

描述

问题描述
  给定一个年份y和一个整数d,问这一年的第d天是几月几日?
  注意闰年的2月有29天。满足下面条件之一的是闰年:
  1) 年份是4的整数倍,而且不是100的整数倍;
  2) 年份是400的整数倍。
输入格式
  输入的第一行包含一个整数y,表示年份,年份在1900到2015之间(包含1900和2015)。
  输入的第二行包含一个整数d,d在1至365之间。
输出格式
  输出两行,每行一个整数,分别表示答案的月份和日期。
样例输入
2015
80
样例输出
3
21
样例输入
2000
40
样例输出
2
9

分析

用了《王道机试指南》中的思路,一天天增加日期。对于闰年的判断基于二维数组,可以说是很机智了

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int isPrime(int y)
{
    if(y%400==0 || (y%4==0&&y%100!=0))return 1;
    return 0;
}
int months[13][2]={
    0,0,
    31,31,
    28,29,
    31,31,
    30,30,
    31,31,
    30,30,
    31,31,
    31,31,
    30,30,
    31,31,
    30,30,
    31,31
};
struct date{
    int y,m,d;
    void addDay(){
     d ++;

     if(d>months[m][isPrime(y)])
     {
        d = 1; m ++;
        if(m>12)
         {
            m = 1; d = 1;y ++;
         }
     }  

    }
};
int main()
{
    int y,d;
    while(~scanf("%d%d",&y,&d))
    {
        date newday ;
        newday.y = y;
        newday.m = 1;
        newday.d = 1;

        int i = 1;
        while(i<d)
        {
            newday.addDay();
            i++;
        }
        printf("%d\n%d\n",newday.m,newday.d);
    }

}

图形旋转

描述

问题描述
  旋转是图像处理的基本操作,在这个问题中,你需要将一个图像逆时针旋转90度。
  计算机中的图像表示可以用一个矩阵来表示,为了旋转一个图像,只需要将对应的矩阵旋转即可。
输入格式
  输入的第一行包含两个整数n, m,分别表示图像矩阵的行数和列数。
  接下来n行每行包含m个整数,表示输入的图像。
输出格式
  输出m行,每行包含n个整数,表示原始矩阵逆时针旋转90度后的矩阵。
样例输入
2 3
1 5 3
3 2 4
样例输出
3 4
5 2
1 3
评测用例规模与约定
  1 ≤ n, m ≤ 1,000,矩阵中的数都是不超过1000的非负整数。

分析

after[i][j] = ori[j][m-i+1];
思路就是按照翻转后的列来往里面填充,就比较容易能找到规律了

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
int ori[1005][1005];
int after[1005][1005];
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i = 1;i<=n;i++)
        for(int j = 1;j<=m;j++)
        scanf("%d",&ori[i][j]);

        for(int i = 1;i<=m;i++)
        for(int j =1;j<=n;j++)
        {
            after[i][j] = ori[j][m-i+1];
        }

        for(int i = 1;i<=m;i++)
        {
            for(int j = 1;j<=n;j++)
            {printf("%d ",after[i][j]);
            }
            printf("\n");
        }

    }

}

数字排序

描述

问题描述
  给定n个整数,请统计出每个整数出现的次数,按出现次数从多到少的顺序输出。
输入格式
  输入的第一行包含一个整数n,表示给定数字的个数。
  第二行包含n个整数,相邻的整数之间用一个空格分隔,表示所给定的整数。
输出格式
  输出多行,每行包含两个整数,分别表示一个给定的整数和它出现的次数。按出现次数递减的顺序输出。如果两个整数出现的次数一样多,则先输出值较小的,然后输出值较大的。
样例输入
12
5 2 3 3 1 3 4 2 5 2 3 5
样例输出
3 4
2 3
5 3
1 1
4 1
评测用例规模与约定
  1 ≤ n ≤ 1000,给出的数都是不超过1000的非负整数。

分析

先用map计数每个数字出现的次数。但是map默认是按key从小到大排序的,不可以,所以又将结果存入到struct中对struct按照规则排序得到结果;

看到网上的另一种思路是两层遍历,找序号最小又最大的

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
map<int,int>cnt;
struct PAIR{
    int key,value;

}p[1005];
    bool cmp(PAIR &a,PAIR &b)
    {
        if(a.value!=b.value)return a.value>b.value;
        else return a.key<b.key;
    }
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int x;
        cnt.clear();

        for(int i = 0;i<n;i++)
        {
            cin>>x;
            cnt[x]++;
        }
        map<int,int>::iterator it;
        int pos = 0;
        for(it = cnt.begin();it!=cnt.end();it++)
        {
            p[pos].key = it->first;
            p[pos].value = it->second;
            pos++;
        }
        sort(p,p+pos,cmp);
        for(int i =0;i<pos;i++)
        {
            printf("%d %d\n",p[i].key,p[i].value);
        }
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值