蓝桥杯寒假Week(2)

目录

1.试题 基础练习 杨辉三角形

2.试题 基础练习 字母图形

3.试题 基础练习 特殊的数字

4.试题 基础练习 回文数

5.试题 基础练习 2n皇后问题

6.试题 算法训练 单词接龙

7.试题 算法训练 粘木棍


1.试题 基础练习 杨辉三角形

资源限制

内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数。

  

它的一个重要性质是:三角形中的每个数字等于它两肩上的数字相加。

  

下面给出了杨辉三角形的前4行:

  

1

  

1 1

  

1 2 1

  

1 3 3 1

  

给出n,输出它的前n行。

输入格式

输入包含一个数n。

输出格式

输出杨辉三角形的前n行。每一行从这一行的第一个数开始依次输出,中间使用一个空格分隔。请不要在前面输出多余的空格。

样例输入

4

样例输出

1

1 1

1 2 1

1 3 3 1

数据规模与约定

1 <= n <= 34。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1100;
int f[N][N];
int n;

int main()
{
    cin>>n;
    f[1][1]=1;
    for(int i=2;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            f[i][j]=f[i-1][j]+f[i-1][j-1];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            cout<<f[i][j]<<" ";
        }
        puts("");
    }
    return 0;
}

2.试题 基础练习 字母图形

资源限制

内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

利用字母可以组成一些美丽的图形,下面给出了一个例子:

ABCDEFG

BABCDEF

CBABCDE

DCBABCD

EDCBABC

这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。

输入格式

输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。

输出格式

输出n行,每个m个字符,为你的图形。

样例输入

5 7

样例输出

ABCDEFG

BABCDEF

CBABCDE

DCBABCD

EDCBABC

数据规模与约定

1 <= n, m <= 26。

#include<stdio.h>
int main()
{
    char ch[26][26];
    int i,j,m,n;
    scanf("%d %d",&m,&n);
    for(i=0;i<n;i++)
        ch[0][i]=i+'A';
    for(i=1;i<m;i++)
    {
        ch[i][0]=i+'A';
        for(j=1;j<n;j++)
        {
            ch[i][j]=ch[i-1][j-1];
        }
    }
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            printf("%c",ch[i][j]);
        }
        printf("\n");
    }
    return 0;
}

3.试题 基础练习 特殊的数字

资源限制

内存限制:512.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

  153是一个非常特殊的数,它等于它的每位数字的立方和,即153=1*1*1+5*5*5+3*3*3。编程求所有满足这种条件的三位十进制数。

输出格式

  按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。

#include <stdio.h>
#include <math.h>

int main() {
    int i,a,b,c;
    for(i=100;i<1000;i++)
    {
        a=i/100;
        b=i/10%10;
        c=i%10;
        if(i==pow(a,3)+pow(b,3)+pow(c,3))
        {
            printf("%d\n",i);
        }
    } 
    return 0;
}

4.试题 基础练习 回文数

资源限制

内存限制:512.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

  1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。

输出格式

  按从小到大的顺序输出满足条件的四位十进制数。

#include<stdio.h> 
 
int main()  
{  
    int i;
    int a1,a2,a3,a4;
    
     for(i=1000;i<10000;i++){
         a1=i/1000%10;
         a2=i/100%10;
         a3=i/10%10;
         a4=i%10;
         if(a1==a4&&a2==a3)
             printf("%d\n",i);
     }
     
    return 0;  
} 

5.试题 基础练习 2n皇后问题

问题描述

  给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。

输入格式

  输入的第一行为一个整数n,表示棋盘的大小。

  接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。

输出格式

  输出一个整数,表示总共有多少种放法。

样例输入

4

1 1 1 1

1 1 1 1

1 1 1 1

1 1 1 1

样例输出

2

样例输入

4

1 0 1 1

1 1 1 1

1 1 1 1

1 1 1 1

样例输出

0

思路

2n皇后问题和8皇后问题思路几乎没有区别,可按照全排列的搜索顺序:

依次每一行放一个皇后,放在某一列,dfs遍历所有可能值(如n=3时有 123 132 213 231 312 321)

剪枝,排除有行列对角线冲突的情况

(1)先放黑皇后,检查格子是否为1及有无行列对角线冲突

(2)再放白皇后,检查格子是否为1及有无行列对角线冲突,以及有无黑皇后

注意:看行列对角线冲突时,黑的是黑的,白的是白的,都是两者的内部冲突,相互不干扰

最终anser即,每种黑皇后的结果中白皇后anser的和.

#include<iostream>
#include<cstdio>
using namespace std;

const int N = 20;
int n, ans;
bool mp[N][N], b[N][N];
bool bdui[N], budui[N], bcol[N];
bool wdui[N], wudui[N], wcol[N];

void white(int u){//后放 
    if(u == n){
        ans ++;  
        return;
    }
    for(int i = 0; i < n; i ++ )
        if(!wcol[i] && !wdui[u + i] && !wudui[i - u + n] && mp[u][i] && !b[u][i]){
            wcol[i] = wdui[u + i] = wudui[i - u + n] = true;
            white(u + 1);
            wcol[i] = wdui[u + i] = wudui[i - u + n] = false;
        }

}

void black(int u){//先放 
    if(u == n){
        white(0);  
        return;
    }
    for(int i = 0; i < n; i ++ )
        if(!bcol[i] && !bdui[u + i] && !budui[i - u + n] && mp[u][i]){
            b[u][i] = true;
            bcol[i] = bdui[u + i] = budui[i - u + n] = true;
            black(u + 1);
            bcol[i] = bdui[u + i] = budui[i - u + n] = false;
            b[u][i] = false;
        }
}

int main(){
    cin >> n;
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < n; j ++ )
            scanf("%d", &mp[i][j]);
            
    black(0);
    cout << ans << endl;
    return 0;
} 

6.试题 算法训练 单词接龙

问题描述

  单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如 beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at 和 atide 间不能相连。

输入格式

  输入的第一行为一个单独的整数n (n<=20)表示单词数,以下n 行每行有一个单词,输入的最后一行为一个单个字符,表示“龙”开头的字母。你可以假定以此字母开头的“龙”一定存在.

输出格式

  只需输出以此字母开头的最长的“龙”的长度

样例输入

  5

  at

  touch

  cheat

  choose

  tact

  a

样例输出

23

样例说明

  连成的“龙”为atoucheatactactouchoose

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=21;

int n;//单词数
string str[N];//怎么说也要让输入的那些单词有 地方住呀
              //这里的N表示单词数的最多的个数限度
int g[N][N]={0};//两个单词之间能够重合的最短长度
int ans=0;//记录龙的长度
int used[N]={0};//每个单词使用的次数 

void dfs(string dragon,int last)
{
    ans=max((int)dragon.size(),ans);
    //现在龙的长度,强制转换是因为string的size是无符号长整型
    
    used[last]++;//使用次数+1

    //寻找它的下一个单词
    for(int i=0;i<n;i++)
    {
       if(g[last][i]&&used[i]<2)//如果跟第i个单词有重复部分,就接上
         dfs(dragon+str[i].substr(g[last][i]),i);
    }
   used[last]--;
   //我来解释一下大多数blog都没讲到的为什么要恢复现场
   //就好比例子来说,touch是第一个被接上的单词
   //那么这个touch在履行完它接龙的责任之后这个循环就结束了呀
   //本来是要由于递归回到at的让人家at继续挑选看看能不能接上其他重合的单词的另一条龙
   //那么好嘞,你at要接上另一条龙了,就说明龙里面已经不是touch作老二了
   //那你是不是要把人家touch还回去,要用的时候再借嘛
   //ok,就是这样。
}

int main()
{
   cin>>n;
   for(int i=0;i<n;i++)
   cin>>str[i];
   
   char sign;
   cin>>sign;//给定一个开头字母 


   //为了枚举字符串之间相同的字串合并形式
   //必须有预处理出来的字符串之间的相同子串邻接表
   //总不能一遍一遍算吧,得有个表
   for(int i=0;i<n;i++)
   {
      for(int j=0;j<n;j++)//也有可能跟自己egtact
      {
         string a=str[i];//当前的单词
         string b=str[j];//被对照的单词 
         for(int k=1;k<min(a.size(),b.size());k++)
         //不用等于是因为不能是包含关系
         //k表示重复的字串的字符个数
         {
            if(a.substr(a.size()-k)==b.substr(0,k))
            //求最小相同字串才能得出最长的龙
            //重合的越多,龙越短
            {
                 g[i][j]=k;
                 break;
             }
        }
      }
   }

     for(int i=0;i<n;i++)//从第一个单词开始
     {
          if(str[i][0]==sign)
          dfs(str[i],i);
          //第一个参数代表现在的龙的现状
          //第二个参数代表此时操作的单词的坐标
     }

     cout<<ans;
          
     return 0;
     }

7.试题 算法训练 粘木棍

资源限制

内存限制:256.0MB C/C++时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s

问题描述

  有N根木棍,需要将其粘贴成M个长木棍,使得最长的和最短的的差距最小。

输入格式

  第一行两个整数N,M。

  一行N个整数,表示木棍的长度。

输出格式

  一行一个整数,表示最小的差距

样例输入

3 2

10 20 40

样例输出

10

数据规模和约定

N, M<=7

思路:每个木棍在分成m堆时,每堆都可以选择粘或者不粘,用dfs枚举所有方案然后找出来最小即可。

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

const int N=10;

int a[N];
bool st[N];
int add[N];

int n,m;
int ans=1e9;

void dfs(int u)
{
    if(u>n)
    {
        for(int i=1;i<=n;i++)
            if(!st[i]) return ;
        int Max=add[1],Min=add[1];
        for(int i=2;i<=m;i++)
        {
            Max=max(Max,add[i]);
            Min=min(Min,add[i]);
        }

        ans=min(ans,Max-Min);
        return ;
    }

    for(int i=1;i<=m;i++)
    {
        //粘
        add[i]+=a[u];
        st[u]=true;
        dfs(u+1);
        add[i]-=a[u];
        st[u]=false;

        //不粘
        dfs(u+1);
    }
}

int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    dfs(1);
    cout<<ans<<endl;
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值