zoukankan      html  css  js  c++  java
  • 第八届蓝桥杯省赛真题题解

    2017年蓝桥杯试题解析

    不得不说自己还是太菜了,2017年蓝桥杯填空题自己就措手不及了。。

    t1标题:迷宫###

    X星球的一处迷宫游乐场建在某个小山坡上。
    它是由10x10相互连通的小房间组成的。
    房间的地板上写着一个很大的字母。
    我们假设玩家是面朝上坡的方向站立,则:
    L表示走到左边的房间,R表示走到右边的房间,
    U表示走到上坡方向的房间,D表示走到下坡方向的房间。
    X星球的居民有点懒,不愿意费力思考。
    他们更喜欢玩运气类的游戏。这个游戏也是如此!
    开始的时候,直升机把100名玩家放入一个个小房间内。
    玩家一定要按照地上的字母移动。
    迷宫地图如下:
    UDDLUULRUL
    UURLLLRRRU
    RRUURLDLRD
    RUDDDDUUUU
    URUDLLRRUU
    DURLRLDLRL
    ULLURLLRDU
    RDLULLRDDD
    UUDDUDUDLL
    ULRDLUURRR
    请你计算一下,最后,有多少玩家会走出迷宫?
    而不是在里边兜圈子。
    请提交该整数,表示走出迷宫的玩家数目,不要填写任何多余的内容。

    思路

    考虑到每一个位置的方向是固定的,所以只要玩家走到之前走过的(已经标记的)的格子上,视为无法走出格子。dfs的出口是玩家走出房间边界,ans++。对每一个格子分别dfs搜索。

    代码

    #include <iostream>
    using namespace std;
    string data[10];
    int ans;
    int vis[10][10];
    bool solve(int i, int j) {
        if (i < 0 || i > 9 || j < 0 || j > 9)
            return true;
        if(vis[i][j]==1)
            return false;
        vis[i][j] = 1;
        switch(data[i][j]){
            case 'U':
                return solve(i-1,j);
            case 'D':
                return solve(i+1,j);
            case 'L':
                return solve(i,j-1);
            case 'R':
                return solve(i,j+1);
            default:
                return false;
        }
    }
    int main() {
        data[0] = "UDDLUULRUL";data[1] = "UURLLLRRRU";
        data[2] = "RRUURLDLRD";data[3] = "RUDDDDUUUU";
        data[4] = "URUDLLRRUU";data[5] = "DURLRLDLRL";
        data[6] = "ULLURLLRDU";data[7] = "RDLULLRDDD";
        data[8] = "UUDDUDUDLL";data[9] = "ULRDLUURRR";
        for (int i = 0; i < 10; ++i) {
            for (int j = 0; j < 10; ++j) {
                memset(vis,0, sizeof(vis));
                if (solve(i, j))
                    ans++;
            }
        }
        cout << ans << endl;
        return 0;
    }
    

    t2标题:跳蚱蜢

    如图所示:

    有9只盘子,排成1个圆圈。
    其中8只盘子内装着8只蚱蜢,有一个是空盘。
    我们把这些蚱蜢顺时针编号为 1~8
    每只蚱蜢都可以跳到相邻的空盘中,
    也可以再用点力,越过一个相邻的蚱蜢跳到空盘中。
    请你计算一下,如果要使得蚱蜢们的队形改为按照逆时针排列,
    并且保持空盘的位置不变(也就是1-8换位,2-7换位,...),至少要经过多少次跳跃?
    注意:要求提交的是一个整数,请不要填写任何多余内容或说明文字。

    思路

    求最少次数,考虑bfs,接下来就是如何设计这个bfs了。首先把圆盘的数字和空格处理成一个字符串,表示当前的状态,如何和目标状态相同,则找到最优答案。考虑每一步的状态转移,空格左右相邻的两个数字都可以和空格互换,为方便空格的定位,而且题目要求空格的位置不变,所以状态中也应该考虑空格的位置。因为要求步数,附加一个参数cnt计数。tips:set去重

    #include<iostream>
    #include<cstring> 
    #include<queue>
    #include<string>
    #include<set>//去重 
    using namespace std;
    string start = "012345678";
    string target = "087654321";
    struct node{
    	string a;
    	int pos0;
    	int cnt;
    	node(string a,int pos0,int cnt):a(a),pos0(pos0),cnt(cnt){
    	}
    	
    };
    queue<node>que;
    void swap(string &str,int a,int b){
    	char t=str[a];
    	str[a]=str[b];
    	str[b]=t;
    }
    set<string>se;//默认排序 
    
    void fun(string s,int pos,int cnt,int new_pos){
    	swap(s,pos,new_pos);
    	if(se.find(s)==se.end()){
    		se.insert(s);
    		que.push(node(s,new_pos,cnt+1)); 
    	}
    }
    int bfs(){
        que.push(node(start,0,0));
        se.insert(start);
        while(!que.empty()){
        	node sta=que.front();
        	if(sta.a==target){
        		return sta.cnt;
    		}
    		int pos=sta.pos0;
    		int new_pos=(pos-1+9)%9;
    		fun(sta.a ,sta.pos0,sta.cnt,new_pos);
    	    new_pos=(pos+1+9)%9;
    		fun(sta.a ,sta.pos0,sta.cnt,new_pos);
    		  new_pos=(pos-2+9)%9;
    		fun(sta.a ,sta.pos0,sta.cnt,new_pos);
    		  new_pos=(pos+2+9)%9;
    		fun(sta.a ,sta.pos0,sta.cnt,new_pos);
    		que.pop();
    	}
    	
    }
    int main(){
    	  cout<< bfs()<<endl;
          return 0;
    } 
    

    t3标题:魔方状态

    二阶魔方就是只有2层的魔方,只由8个小块组成。
    如图所示。

    小明很淘气,他只喜欢3种颜色,所以把家里的二阶魔方重新涂了颜色,如下:

    前面:橙色
    右面:绿色
    上面:黄色
    左面:绿色
    下面:橙色
    后面:黄色

    请你计算一下,这样的魔方被打乱后,一共有多少种不同的状态。

    如果两个状态经过魔方的整体旋转后,各个面的颜色都一致,则认为是同一状态。

    请提交表示状态数的整数,不要填写任何多余内容或说明文字。

    思路

    这个题就没有写了。。。
    题解传送门

    t4标题:方格分隔

    6x6的方格,沿着格子的边线剪开成两部分。
    要求这两部分的形状完全相同。

    如图:

    就是可行的分割法。

    试计算:
    包括这3种分法在内,一共有多少种不同的分割方法。
    注意:旋转对称的属于同一种分割法。
    请提交该整数,不要填写任何多余的内容或说明文字。

    思路

    首先考虑的是T字型,dfs是跑不出来的,那这个题该怎样解决呢?
    首先两个部分是关于中心对称的,把坐标(3,3)作为中心点。
    可以考虑用dfs跑方格的切割线,标记走过的点,同时标记对称点,但搜索到边界,ans++。考虑四个方向同时搜索到,最后答案除4。

    #include <iostream>
    #include<cstring>
    using namespace std;
    int ans=0;
    //int dx[4]={0,1,-1,0};
    //int dy[4]={-1,0,0,1};
    int dire[][2] = {{-1, 0},
                     {1,  0},
                     {0,  -1},
                     {0,  1}};
    int vis[7][7];
    void dfs(int x,int y){
       if (x == 0 || y == 0 || x == 6 || y == 6) {
            ans++;
            return;
        }
    	vis[x][y]=1;
    	vis[6-x][6-y]=1;
    	for(int i=0;i<4;i++){
    		int nx=x+dire[i][0],ny=y+dire[i][1];
    		if(nx>=0&&nx<=6&&ny>=0&&ny<=6&&!vis[nx][ny]){
    			dfs(nx,ny);
    				vis[nx][ny]=0;
    		vis[6-nx][6-ny]=0;
    		}
    	}
    
    } 
    int main() {
        dfs(3, 3);
        cout << ans / 4 << endl;
        return 0;
    }
    

    代码填空题较为简单,在此不写了

    t7正则问题

    考虑一种简单的正则表达式:
    只由 x ( ) | 组成的正则表达式。
    小明想求出这个正则表达式能接受的最长字符串的长度。

    例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是: xxxxxx,长度是6。

    输入

    一个由x()|组成的正则表达式。输入长度不超过100,保证合法。

    输出

    这个正则表达式能接受的最长字符串的长度。

    例如,
    输入:
    ((xx|xxx)x|(x|xx))xx

    程序应该输出:
    6
    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 1000ms

    思路

    这个题开始完全看不懂题意。题意是:|表示或,左右取一个较大的连续的x,例如:xxx|xx就是3,最后问最大的连续的是多少,()有最高优先级。求连续的x的个数。运用递归,处理(,求解子问题,加深一层,遇到),退出一层。这个题有点类似表达式的处理,自己也是没能写出来。

    代码

    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    char s[100];
    int len;
    int pos;
    /*求出当前字符串,自当前下标到结束能匹配的字符串的长度*/
    int f() {
        int m = 0;
        int tmp = 0;//用于保存连续的x的数量
        while (pos < len) {
            if (s[pos] == '(') {
                pos++;
                tmp += f();//等待后面的结果并累加到ans
            } else if (s[pos] == 'x') {//
                pos++;
                tmp++;
            } else if (s[pos] == '|') {
                pos++;
                m = max(m, tmp);
                tmp = 0;
            } else if (s[pos] == ')') {
                pos++;
                m = max(m, tmp);
                return m;
            }
        }
        m = max(m, tmp);
        return m;
    }
    int main() {
        scanf("%s", &s);
        len = strlen(s);
        int ans = f();
        printf("%d
    ", ans);
        return 0;
    }
    

    t8包子凑数

    小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子。
    每种蒸笼都有非常多笼,可以认为是无限笼。

    每当有顾客想买X个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有X个包子。
    比如一共有3种蒸笼,分别能放3、4和5个包子。
    当顾客想买11个包子时,大叔就会选2笼3个的再加1笼5个的(也可能选出1笼3个的再加2笼4个的)。
    当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有3种蒸笼,分别能放4、5和6个包子。
    而顾客想买7个包子时,大叔就凑不出来了。
    小明想知道一共有多少种数目是包子大叔凑不出来的。

    输入

    第一行包含一个整数N。(1 <= N <= 100)
    以下N行每行包含一个整数Ai。(1 <= Ai <= 100)

    输出

    一个整数代表答案。如果凑不出的数目有无限多个,输出INF。

    例如,
    输入:
    2
    4
    5
    程序应该输出:
    6
    再例如,
    输入:
    2
    4
    6
    程序应该输出:
    INF
    样例解释:
    对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。
    对于样例2,所有奇数都凑不出来,所以有无限多个。
    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 1000ms

    思路

    之前蓝桥杯出现一个题,给定两个数a,b求出他们最大不能凑数的数。这个题思路就是如果他们互质,那么这个数是ab-a-b,否则就是INF。那么对于这个题,计算不能凑数的个数,如何他们之间的gcd!=1,则是INF,否则这样考虑:问题规模比较小,最大不能凑数的数肯定小于10000
    。所以用O(n
    n*n)的规模可以在时限下面解决。
    tips:对于每个数0~10000,用vis数组标记他们是否可以凑出,对以及扩展的数不断加上其它的数,来改变vis数组标记,最后遍历vis数组即可。

    代码

    #include<iostream>
    using namespace std;
    int gcd(int a, int b) {
    	return a % b == 0 ? b : gcd(b, a%b);
    }
    
    int a[101];
    bool f[10101];
    int gc;
    int ans = 0;
    int main() {
    	int n;
    	cin >> n;
    	f[0] = true;
    	for (int i = 0; i<n; i++) {
    		cin >> a[i];
    		if (i == 0)gc = a[i];
    		else gc = gcd(a[i], gc);
    		for (int j = 0; j < 10000; ++j) {
    			if (f[j])
    				f[j + a[i]] = true;
    		}
    	}
    	if (gc != 1) {
    		cout << "INF
    ";
    
    	}
    	else {
    		for (int i = 0; i<10000; i++)
    			if (!f[i])ans++;
    		cout << ans << endl;
    	}
    	
    	return 0;
    }
    

    t9分巧克力

    儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
    小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。
    
    为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:
    
    1. 形状是正方形,边长是整数
    2. 大小相同
    

    例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。
    当然小朋友们都希望得到的巧克力尽可能大,你能帮小明计算出最大的边长是多少么?
    输入
    第一行包含两个整数N和K。(1 <= N, K <= 100000)
    以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000)
    输入保证每位小朋友至少能获得一块1x1的巧克力。
    输出
    输出切出的正方形巧克力最大可能的边长。
    样例输入:
    2 10
    6 5
    5 6
    样例输出:
    2
    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 1000ms

    思路

    较为明显的二分+check,二分可能的边长

    代码

    #include <stdio.h>
    #include <cstring>
    #include <algorithm>
    #include<iostream> 
    using namespace std;
    const int N=1e5+10;
    struct node{
    	int x,y;
    }a[N];
    int n,k;
    bool check(int w){
    	int ans=0;
    	for(int i=0;i<n;i++){
    		ans+=(a[i].x/w)*(a[i].y/w);
    	}
    	return ans>=k;
    }
    int ans;
    int main(){
    
    	cin>>n>>k;
    	for(int i=0;i<n;i++){
    		cin>>a[i].x >>a[i].y;
    	}
    	int l=1,r=N;
    	int mid; 
    	while(l<=r){
    		mid=(l+r)/2;
    		if(check(mid)){
    			l=mid+1;
    			ans=mid;
    		}
    		else r=mid-1;
    	}
    	cout<<ans<<endl;//不能输出mid 
    	return 0;
    }
    

    t10油漆面积

    X星球的一批考古机器人正在一片废墟上考古。
    该区域的地面坚硬如石、平整如镜。
    管理人员为方便,建立了标准的直角坐标系。
    每个机器人都各有特长、身怀绝技。它们感兴趣的内容也不相同。
    经过各种测量,每个机器人都会报告一个或多个矩形区域,作为优先考古的区域。
    矩形的表示格式为(x1,y1,x2,y2),代表矩形的两个对角点坐标。
    为了醒目,总部要求对所有机器人选中的矩形区域涂黄色油漆。
    小明并不需要当油漆工,只是他需要计算一下,一共要耗费多少油漆。
    其实这也不难,只要算出所有矩形覆盖的区域一共有多大面积就可以了。
    注意,各个矩形间可能重叠。
    本题的输入为若干矩形,要求输出其覆盖的总面积。
    输入格式:
    第一行,一个整数n,表示有多少个矩形(1<=n<10000)
    接下来的n行,每行有4个整数x1 y1 x2 y2,空格分开,表示矩形的两个对角顶点坐标。
    (0<= x1,y1,x2,y2 <=10000)
    输出格式:
    一行一个整数,表示矩形覆盖的总面积面积。
    例如,
    输入:
    3
    1 5 10 10
    3 1 20 20
    2 7 15 17
    程序应该输出:
    340
    再例如,
    输入:
    3
    5 2 10 6
    2 7 12 10
    8 1 15 15
    程序应该输出:
    128
    资源约定:
    峰值内存消耗(含虚拟机) < 256M
    CPU消耗 < 2000ms

    线段树加扫描线的模板题,手写不出线段树。

    题解传送门

    不疯魔不成活
  • 相关阅读:
    在mysql中计算百分比
    给指定的div增加滚动条
    Java高效编程之三【类和接口】
    Linux(CentOS) 如何查看当前占用CPU或内存最多的K个进程
    MapReduce:详解Shuffle过程
    Java高效编程之二【对所有对象都通用的方法】
    Java高效编程之一【创建和销毁对象】
    ANT命令总结(转载)
    linux 压缩文件的命令总结
    Cloudera CDH 、Impala本地通过Parcel安装配置详解
  • 原文地址:https://www.cnblogs.com/gzr2018/p/10577952.html
Copyright © 2011-2022 走看看