CCF 2014 真题 持续更新

门禁系统

描述

问题描述
  涛涛最近要负责图书馆的管理工作,需要记录下每天读者的到访情况。每位读者有一个编号,每条记录用读者的编号来表示。给出读者的来访记录,请问每一条记录中的读者是第几次出现。
输入格式
  输入的第一行包含一个整数n,表示涛涛的记录条数。
  第二行包含n个整数,依次表示涛涛的记录中每位读者的编号。
输出格式
  输出一行,包含n个整数,由空格分隔,依次表示每条记录中的读者编号是第几次出现。
样例输入
5
1 2 1 1 3
样例输出
1 1 2 3 1
评测用例规模与约定
  1≤n≤1,000,读者的编号为不超过n的正整数。

分析

开一个数组用哈希的思想来记录就好了,数据范围也不大,数组完全ok

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int coun[1005];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i = 0;i<=n;i++)coun[i] = 0;
        int x ;
        for(int i = 1;i<=n;i++)
        {
            scanf("%d",&x);
            coun[x]++;
            cout<<coun[x]<<" ";
        }
        cout<<"\n";
    }
}

Z字形扫描

描述

问题描述
  在图像编码的算法中,需要将一个给定的方形矩阵进行Z字形扫描(Zigzag Scan)。给定一个n×n的矩阵,Z字形扫描的过程如下图所示:

  对于下面的4×4的矩阵,
  1 5 3 9
  3 7 5 6
  9 4 6 4
  7 3 1 3
  对其进行Z字形扫描后得到长度为16的序列:
  1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
  请实现一个Z字形扫描的程序,给定一个n×n的矩阵,输出对这个矩阵进行Z字形扫描的结果。
输入格式
  输入的第一行包含一个整数n,表示矩阵的大小。
  输入的第二行到第n+1行每行包含n个正整数,由空格分隔,表示给定的矩阵。
输出格式
  输出一行,包含n×n个整数,由空格分隔,表示输入的矩阵经过Z字形扫描后的结果。
样例输入
4
1 5 3 9
3 7 5 6
9 4 6 4
7 3 1 3
样例输出
1 5 3 9 7 3 9 5 4 7 3 6 6 4 1 3
评测用例规模与约定
  1≤n≤500,矩阵元素为不超过1000的正整数。

分析

比较常见的题,找到规律就可以了。按照z的周期来

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int ku[503][503];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i = 1;i<=n;i++)
        for(int j = 1;j<=n;j++)
        scanf("%d",&ku[i][j]);

        int i = 1,j = 1;
        cout<<ku[i][j]<<" ";
        while(i<n || j<n)
        {
            if(j+1<=n)j++;
            else i++;
            cout<<ku[i][j]<<" ";
            while(j>1 && i<n)
            {
                i++;j--;
                cout<<ku[i][j]<<" ";
            }
            if(i+1<=n)i++;
            else j++;
            cout<<ku[i][j]<<" ";

            while(j<n && i>1)
            {
                i--;j++;
                cout<<ku[i][j]<<" ";
            }
        }
        cout<<"\n";

    }
}

画图

描述

问题描述
  在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色。
  下图给出了一个画了两个矩形的例子。第一个矩形是(1,1) 到(4, 4),用绿色和紫色表示。第二个矩形是(2, 3)到(6, 5),用蓝色和紫色表示。图中,一共有15个单位的面积被涂上颜色,其中紫色部分被涂了两次,但在计算面积时只计算一次。在实际的涂色过程中,所有的矩形都涂成统一的颜色,图中显示不同颜色仅为说明方便。

  给出所有要画的矩形,请问总共有多少个单位的面积被涂上颜色。
输入格式
  输入的第一行包含一个整数n,表示要画的矩形的个数。
  接下来n行,每行4个非负整数,分别表示要画的矩形的左下角的横坐标与纵坐标,以及右上角的横坐标与纵坐标。
输出格式
  输出一个整数,表示有多少个单位的面积被涂上颜色。
样例输入
2
1 1 4 4
2 3 6 5
样例输出
15
评测用例规模与约定
  1<=n<=100,0<=横坐标、纵坐标<=100。

分析

数据量不大,所以直接计数就好了
以area[i][j]表示以(i,j)为左下角顶点的单位为1的小格子,初始全是0,在范围内的就标1并且计数,最后输出结果

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int area[105][105];

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int sum = 0;
        int x1,y1,x2,y2;
        for(int i = 0;i<=n;i++)
        for(int j = 0;j<=n;j++)
        area[i][j] = 0;

        for(int i =0;i<n;i++)
        {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);  
             for(int s = x1;s<x2;s++)
              for(int e = y1;e<y2;e++)
              {
                if(area[s][e]==0)
                {
                    area[s][e] = 1; sum ++;
                  }
              }
        }
        cout<<sum<<"\n";
    }
}

字符串匹配

描述

问题描述
  给出一个字符串和多行文字,在这些文字中找到字符串出现的那些行。你的程序还需支持大小写敏感选项:当选项打开时,表示同一个字母的大写和小写看作不同的字符;当选项关闭时,表示同一个字母的大写和小写看作相同的字符。
输入格式
  输入的第一行包含一个字符串S,由大小写英文字母组成。
  第二行包含一个数字,表示大小写敏感的选项,当数字为0时表示大小写不敏感,当数字为1时表示大小写敏感。
  第三行包含一个整数n,表示给出的文字的行数。
  接下来n行,每行包含一个字符串,字符串由大小写英文字母组成,不含空格和其他字符。
输出格式
  输出多行,每行包含一个字符串,按出现的顺序依次给出那些包含了字符串S的行。
样例输入
Hello
1
5
HelloWorld
HiHiHelloHiHi
GrepIsAGreatTool
HELLO
HELLOisNOTHello
样例输出
HelloWorld
HiHiHelloHiHi
HELLOisNOTHello
样例说明
  在上面的样例中,第四个字符串虽然也是Hello,但是大小写不正确。如果将输入的第二行改为0,则第四个字符串应该输出。
评测用例规模与约定
  1<=n<=100,每个字符串的长度不超过100。

分析

这里主要用了c++ string里的find()函数
string :: size_type position = s.find(s2);
if position != s.npos就是找到了
然后在大小写不敏感的时候全部转化成小写来匹配

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

string strs[105];
string little[105];
int main()
{
    string input;
    while(cin>>input)
    {
        int opt,n;

        scanf("%d%d",&opt,&n);
        for(int i = 0;i<n;i++)
        {
        cin>>strs[i];
        for(int j = 0;j<strs[i].length();j++)
        little[i] += tolower(strs[i][j]);
    }
    string::size_type position;
        if(opt == 0)
        {
            transform(input.begin(),input.end(),input.begin(),::tolower);

            for(int i = 0;i<n;i++)
            {
                position = little[i].find(input);
                if(position != little[i].npos)cout<<strs[i]<<"\n";
            }
        }
        else{
            for(int i = 0;i<n;i++)
            {
                position = strs[i].find(input);
                if(position != strs[i].npos)cout<<strs[i]<<"\n";
            }
        }
    }
}

相反数

描述

问题描述
  有 N 个非零且各不相同的整数。请你编一个程序求出它们中有多少对相反数(a 和 -a 为一对相反数)。
输入格式
  第一行包含一个正整数 N。(1 ≤ N ≤ 500)。
  第二行为 N 个用单个空格隔开的非零整数,每个数的绝对值不超过1000,保证这些整数各不相同。
输出格式
  只输出一个整数,即这 N 个数中包含多少对相反数。
样例输入
5
1 2 3 -1 -2
样例输出
2

分析

比较简单,数量级也不大,排序后一个从头开始找负数,另一个从后开始找有没有对应的正数

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int neg[505],pos[505]; 
bool binSearch(int x,int n)
{
    int goal = -x;
    int begin = 0,end = n-1,mid;
    while(begin<=end)
    {
        mid = (begin+end)/2;
        if(pos[mid]==goal)return true;
        else if(pos[mid]<goal)
        {
            begin = mid + 1;
        }
        else end = mid-1;
    }
    return false;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        for(int i=0;i<n;i++)
        scanf("%d",&neg[i]);
        sort(neg,neg+n);
        int i = 0,j = n-1;
        int ans = 0;
        while(neg[i]<=0)
        {
            for(j = n-1;neg[j]>0;j--)
            if(neg[j]==-neg[i])ans ++;
            i++;
        }
        cout<<ans<<"\n";
    }
}

窗口

描述

问题描述
  在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域。窗口的边界上的点也属于该窗口。窗口之间有层次的区别,在多于一个窗口重叠的区域里,只会显示位于顶层的窗口里的内容。
  当你点击屏幕上一个点的时候,你就选择了处于被点击位置的最顶层窗口,并且这个窗口就会被移到所有窗口的最顶层,而剩余的窗口的层次顺序不变。如果你点击的位置不属于任何窗口,则系统会忽略你这次点击。
  现在我们希望你写一个程序模拟点击窗口的过程。
输入格式
  输入的第一行有两个正整数,即 N 和 M。(1 ≤ N ≤ 10,1 ≤ M ≤ 10)
  接下来 N 行按照从最下层到最顶层的顺序给出 N 个窗口的位置。 每行包含四个非负整数 x1, y1, x2, y2,表示该窗口的一对顶点坐标分别为 (x1, y1) 和 (x2, y2)。保证 x1 < x2,y1 2。
  接下来 M 行每行包含两个非负整数 x, y,表示一次鼠标点击的坐标。
  题目中涉及到的所有点和矩形的顶点的 x, y 坐标分别不超过 2559 和  1439。
输出格式
  输出包括 M 行,每一行表示一次鼠标点击的结果。如果该次鼠标点击选择了一个窗口,则输出这个窗口的编号(窗口按照输入中的顺序从 1 编号到 N);如果没有,则输出”IGNORED”(不含双引号)。
样例输入
3 4
0 0 4 4
1 1 5 5
2 2 6 6
1 1
0 0
4 4
0 5
样例输出
2
1
1
IGNORED
样例说明
  第一次点击的位置同时属于第 1 和第 2 个窗口,但是由于第 2 个窗口在上面,它被选择并且被置于顶层。
  第二次点击的位置只属于第 1 个窗口,因此该次点击选择了此窗口并将其置于顶层。现在的三个窗口的层次关系与初始状态恰好相反了。
  第三次点击的位置同时属于三个窗口的范围,但是由于现在第 1 个窗口处于顶层,它被选择。
  最后点击的 (0, 5) 不属于任何窗口。

分析

输入给定的是从底到最顶层,所以想到了用栈来处理,这样可以从上往下检查,只要点的坐标在两个顶点坐标内就可以,上面的弹出后先依次存到另一个栈里,这样查找一遍后从栈2中依次pop 出来push到原栈里,顺序就还是一样的
最后若有选中的,就把选中的加到最顶层
注意这个序号是按输入顺序,而不是顶层为1

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
struct window{
    int x1,x2,y1,y2;
    int id;
};
stack<window>w1;
stack<window>w2;

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i =0;i<n;i++)
        {
            window w;
            scanf("%d %d %d %d",&w.x1,&w.y1,&w.x2,&w.y2);
            w.id = (i+1);
            w1.push(w);
        }
        for(int i=0;i<m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            bool flag = false;
            window top;
            while(!w1.empty())
            {
                 top = w1.top();
                window newtop;
                if(x>=top.x1 && x<=top.x2 && y>=top.y1 && y<=top.y2)
                {
                    printf("%d\n",top.id);
                    flag = true;
                    newtop = top;
                    w1.pop();
                    break;
                }
                else{
                    w1.pop();
                    w2.push(top);
                }
            }
            while(!w2.empty())
                {
                    window w2top = w2.top();
                    w1.push(w2top);
                    w2.pop();
                }
            if(flag==false)
            {
                printf("IGNORED\n");

            }
            else
            {
                w1.push(top);
            }


        }
    }
}

猜你喜欢

转载自blog.csdn.net/BeforeEasy/article/details/82425696
今日推荐