2017第八届(C/C++)B组蓝桥国赛题

标题:36进制


对于16进制,我们使用字母A-F来表示10及以上的数字。
如法炮制,一直用到字母Z,就可以表示36进制。

36进制中,A表示10,Z表示35,AA表示370

你能算出 MANY 表示的数字用10进制表示是多少吗?

请提交一个整数,不要填写任何多余的内容(比如,说明文字)

代码:        答案:1040254

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
	int a = 'M' - 'A'+10;
	int b = 'A' - 'A'+10;
	int c = 'N' - 'A' +10;
	int d = 'Y' - 'A' +10;
	int gg = 36*36*36*a+36*36*b +36*c+1*d;
	cout<<gg<<endl;
	return 0;
}


标题:磁砖样式

小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。

小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何2*2的小格子是同一种颜色。

(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝) emmm。。。。。看错题目了

难怪我题解也看不懂

显然,对于 2*3 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】

但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。

注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)



代码: 转载来自:https://www.cnblogs.com/pythonbigdata/p/8905923.html

#include<bits/stdc++.h>
using namespace std;
int a[5][15];
int count=0;
bool judge(int x,int y)
{
    if(a[x][y]==a[x-1][y-1]&&a[x][y]==a[x-1][y]&&a[x][y]==a[x][y-1])
    	return false;
    if(a[x][y]==a[x-1][y]&&a[x][y]==a[x-1][y+1]&&a[x][y]==a[x][y+1])
    	return false;
    if(a[x][y]==a[x][y-1]&&a[x][y]==a[x+1][y-1]&&a[x][y]==a[x+1][y])
    	return false;
    if(a[x][y]==a[x][y+1]&&a[x][y]==a[x+1][y]&&a[x][y]==a[x+1][y+1])
    	return false;
    return true;
}
void dfs(int x,int y){
    if(x==3&&y==10){
        count++;
        return;
    }
    if(y>10){
        dfs(x+1,1);
        return;
    }
    if(a[x][y]==-1){
        if(a[x][y+1]==-1){
            a[x][y]=1;
            a[x][y+1]=1;
            if(judge(x,y)){
                dfs(x,y+1);
            }
            a[x][y]=-1;
            a[x][y+1]=-1;
             
            a[x][y]=2;
            a[x][y+1]=2;
            if(judge(x,y)){
                dfs(x,y+1);
            }
            a[x][y]=-1;
            a[x][y+1]=-1;
     
        }
        if(a[x+1][y]==-1){
            a[x][y]=1;
            a[x+1][y]=1;
            if(judge(x,y)){
                dfs(x,y+1);
            }
            a[x][y]=-1;
            a[x+1][y]=-1;
             
         
            a[x][y]=2;
            a[x+1][y]=2;
            if(judge(x,y)){
                dfs(x,y+1);
            }
            a[x][y]=-1;
            a[x+1][y]=-1;
         
        }    
    }
    else{
        dfs(x,y+1);
    }
}
int main(){
    for(int i=1;i<=3;i++){
        for(int j=1;j<=10;j++){
            a[i][j]=-1;
        }
    }//由于坐标是从1开始并且数组比原本的大因此不必考虑是否越界的问题
    dfs(1,1);
    printf("%d",count);
    return 0;
}





标题:希尔伯特曲线

希尔伯特曲线是以下一系列分形曲线 Hn 的极限。我们可以把 Hn 看作一条覆盖 2^n × 2^n 方格矩阵的曲线,曲线上一共有 2^n × 2^n 个顶点(包括左下角起点和右下角终点),恰好覆盖每个方格一次。

[p1.png]

Hn(n > 1)可以通过如下方法构造:
1. 将 Hn-1 顺时针旋转90度放在左下角
2. 将 Hn-1 逆时针旋转90度放在右下角
3. 将2个 Hn-1 分别放在左上角和右上角
4. 用3条单位线段把4部分连接起来

对于 Hn 上每一个顶点 p ,我们定义 p 的坐标是它覆盖的小方格在矩阵中的坐标(左下角是(1, 1),右上角是(2^n, 2^n),从左到右是X轴正方向,从下到上是Y轴正方向),
定义 p 的序号是它在曲线上从起点开始数第几个顶点(从1开始计数)。

以下程序对于给定的n(n <= 30)和p点坐标(x, y),输出p点的序号。请仔细阅读分析源码,填写划线部分缺失的内容。

注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。

代码:

#include <stdio.h>

long long f(int n, int x, int y) {
    if (n == 0) return 1;
    int m = 1 << (n - 1);
    if (x <= m && y <= m) {
        return f(n - 1, y, x);
    }


    if (x > m && y <= m) {
        return 3LL * m * m + f(n - 1, m - y  + 1, m * 2 - x + 1); //  填空
    }
    if (x <= m && y > m) {
        return 1LL * m * m + f(n - 1, x, y - m);
    }
    if (x > m && y > m) {
        return 2LL * m * m + f(n - 1, x - m, y - m);
    }
}

int main() {
    int n, x, y;
    scanf("%d %d %d", &n, &x, &y);
    printf("%lld", f(n, x, y));

    return 0;
}

 m - y  + 1

怎么说,其实我也不知道这个要怎么,只是 觉得吧 应该就是这么填...............具体可以看这个衔接

https://www.cnblogs.com/chiweiming/p/9010744.html



标题:发现环


小明的实验室有N台电脑,编号1~N。原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络。在树形网络上,任意两台电脑之间有唯一的路径相连。

不过在最近一次维护网络时,管理员误操作使得某两台电脑之间增加了一条数据链接,于是网络中出现了环路。环路上的电脑由于两两之间不再是只有一条路径,使得这些电脑上的数据传输出现了BUG。

为了恢复正常传输。小明需要找到所有在环路上的电脑,你能帮助他吗?

输入
-----
第一行包含一个整数N。
以下N行每行两个整数a和b,表示a和b之间有一条数据链接相连。

对于30%的数据,1 <= N <= 1000
对于100%的数据, 1 <= N <= 100000, 1 <= a, b <= N

输入保证合法。

输出
----
按从小到大的顺序输出在环路上的电脑的编号,中间由一个空格分隔。


样例输入:
5
1 2
3 1
2 4
2 5
5 3

样例输出:
1 2 3 5


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

主要思路是利用并查集的思想还有深搜。

emmmm,就是,因为本身是一个树!所以!只有一个环.....如果当前两个点已经被连接了说明说。。。现在的两个点是一定在环里面的,注意的是,别加进vector里面,因为啊..........如果不加进去,vector其实就是一路走到底的因为没有环就是树就是唯一的一条路走的所以别加到vector里面..........

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm> 
using namespace std;
const int maxn = 100000+10;
int pre[maxn];
vector<int >edge[maxn];
int record[maxn],vis[maxn]; 
int beginn,endd;
void init(int n)
{
	for(int i =1;i<=n;i++)
		pre[i] = i;
}
int findd(int x)
{
	if(pre[x] == x)return x;
	return pre[x] = findd(pre[x]);
}
bool merge(int x,int y)
{
	int fx = findd(x);
	int fy = findd(y);
	if(fx!=fy){
		pre[fx] = fy;
		return true;
	}
	return false;
}
void DFS(int now ,int cnt)
{
	record[cnt] = now;   
	if(now == endd)
	{
		sort(record,record+cnt+1);
		for(int i =0;i<=cnt;i++)
			printf("%d%c",record[i]," \n"[i==cnt]);
		return ;	
	}else 
	{
		int size = edge[now].size();
		for(int i = 0;i<size;i++)
		{
			int gg = edge[now][i];
			if(vis[gg] == 0 )
			{
				vis[gg] = 1;
				DFS(gg,cnt+1);
				vis[gg] = 0;
			}	
		}
	}
	return ; 
}
int main()
{
	int n,x,y;scanf("%d",&n);
	init(n);
	for(int i =1 ;i<= n;i++)
	{
		scanf("%d%d",&x,&y);//如果这两个点放进去之后发现已经连接过了,说明这两个点之间是环中的点 
		if(merge(x,y)==false) 
		{
 			beginn = x;
 			endd = y;//这边如果已经是了的话别放进去了,这样子保证里面的是一个树,找的话一直找下去就好了 
		}else   
		{
			edge[x].push_back(y);
			edge[y].push_back(x);	
		}
	}
	vis[beginn] = 1;
	DFS(beginn,0);
	
    return 0;
}




猜你喜欢

转载自blog.csdn.net/galesaur_wcy/article/details/80314148
今日推荐