蓝桥杯(C、C++)B组 练习第③篇

目录

一.砝码称重

二.乘积最大

三.七段码


一.砝码称重

你有一架天平和 N个砝码,这 N个砝码重量依次是 W_1, W_2, · · · , W_N 

请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。

输入格式
输入的第一行包含一个整数 N。

第二行包含 N 个整数:W_1, W_2, W_3, · · · , W_N 

输出格式
输出一个整数代表答案。

 答案参考:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll N;
ll a[200];
ll summ=0;
ll ans=0;
int dp[200][200000];
//dp[i][j]表示用到前i个砝码,能否称出j重量
//1为可以,0为不可以

int main()
{
  // 请在此输入您的代码
  cin>>N;
  for(int i=1;i<=N;i++){
    cin>>a[i];
    summ+=a[i];
  }

  for(int i=1;i<=N;i++){
    for(int j=1;j<=summ;j++){//遍历所有可能的重量
      dp[i][j]=dp[i-1][j];//继承前一个状态
      if(dp[i][j]==0){//如果普通继承下来,发现这个不行呢?
        if(j==a[i]) dp[i][j]=1;//如果需要的重量正好就是第i个砝码,那么可以
        if(dp[i-1][j+a[i]]==1) dp[i][j]=1;//如果前i-1个能搞出j+a[i]重量,那么把第i个砝码放到另一侧就行
        if(dp[i-1][abs(j-a[i])]==1) dp[i][j]=1;//如果前i-1个砝码能搞出abs(j-a[i])重量
        //那么把第i个砝码放同侧就行
      }
    }
  }

  for(int j=1;j<=summ;j++){
    if(dp[N][j]==1) ans++;//遍历,看dp[][]==1的个数,就是答案
  }
  cout<<ans<<endl;
  return 0;
}

二.乘积最大


  今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡
    江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活
    动的选手出了这样一道题目:
    
    设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。

  同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:

  有一个数字串:312, 当N=3,K=1时会有以下两种分法:

  3*12=36
  31*2=62

  这时,符合题目要求的结果是:31*2=62

  现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

输入格式

  程序的输入共有两行:
  第一行共有2个自然数N,K(6≤N≤40,1≤K≤6)
  第二行是一个长度为N的数字串。


输出格式

  输出所求得的最大乘积(一个自然数)。

  样例输入

  4 2
  1231

       样例 输出:
        62

 答案参考:

#include <stdio.h>
#include <string.h>

#define N_MAX 40
#define K_MAX 6
//首先,在代码中我们定义了一个 `getValue` 函数,该函数用于获取数字串中指定位置范围内的数字的值。
//通过循环遍历指定范围内的字符,并将其转换为整数,然后以十进制形式构建数字。
int getValue(char* digits, int start, int end) {
    int value = 0;
    for (int i = start; i <= end; i++) {
        value = value * 10 + (digits[i] - '0');
    }
    return value;
}
//接下来,我们使用动态规划的方法来解决问题。我们定义一个二维数组 `dp[N_MAX][K_MAX]`,其中 `dp[i][j]` 
//表示将数字串从位置 0 到位置 i 分为 j+1 个部分所得到的最大乘积。动态规划的关键在于找到问题的状态转移方程。

long long int maxValue(char* digits, int N, int K) {
    long long int dp[N_MAX][K_MAX];
    memset(dp, 0, sizeof(dp));
//我们先初始化第一行 `dp[0][j]`,它们的值分别为数字串从位置 0 到位置 j 的数字。然后,我们从第二行开始逐行填充数组。
    for (int i = 0; i < N; i++) {
        dp[i][0] = getValue(digits, 0, i);
    }
//对于每个位置 `(i, k)`,我们需要考虑将数字串从位置 `(k+1, i)` 分割成 j+1 个部分的情况。我们使用一个三层循环。
//外层循环遍历每个 k,表示可能的最后一个乘号的位置,中间层循环遍历 k 之前的位置 j,内层循环遍历 k+1 到 i 之间的位置 p。
    for (int k = 1; k <= K; k++) {
        for (int i = k; i < N; i++) {
            for (int j = k - 1; j < i; j++) {
                long long int product = dp[j][k - 1] * getValue(digits, j + 1, i);
                if (product > dp[i][k]) {
                    dp[i][k] = product;
                }
            }
        }
    }

    return dp[N - 1][K];
}
//在每轮循环中,我们计算将数字串从位置 `(p+1, i)` 分割成 j 个部分的最大乘积 `dp[p][j-1]`,并与数字串从位置 `(j+1, i)` 
//分割为一个部分的乘积 `getValue(digits, j+1, i)` 相乘得到新的乘积。如果这个新的乘积大于 `dp
int main() {
    int N, K;
    char digits[N_MAX + 1];

    scanf("%d %d", &N, &K);
    scanf("%s", digits);

    long long int result = maxValue(digits, N, K);
    printf("%lld\n", result);

    return 0;
}

 

三.七段码

本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。

小蓝要用七段码数码管来表示一种特殊的文字。


上图给出了七段码数码管的一个图示,数码管中一共有 77 段可以发光的二 极管,分别标记为 a, b, c, d, e, f, ga,b,c,d,e,f,g。

小蓝要选择一部分二极管(至少要有一个)发光来表达字符。在设计字符 的表达时,要求所有发光的二极管是连成一片的。

例如:bb 发光,其他二极管不发光可以用来表达一种字符。

例如 cc 发光,其他二极管不发光可以用来表达一种字符。这种方案与上 一行的方案可以用来表示不同的字符,尽管看上去比较相似。

例如:a, b, c, d, ea,b,c,d,e 发光,f, gf,g 不发光可以用来表达一种字符。

例如:b, fb,f 发光,其他二极管不发光则不能用来表达一种字符,因为发光 的二极管没有连成一片。

请问,小蓝可以用七段码数码管表达多少种不同的字符?

答案参考:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int ans = 0;
  for(int a = 0 ; a <= 1 ; a++){
    for(int b = 0 ; b <= 1 ; b++){
      for(int c = 0 ; c <= 1 ; c++){
        for(int d = 0 ; d <= 1 ; d++){
          for(int e = 0 ; e <= 1 ; e++){
            for(int f = 0 ; f <= 1 ; f++){
              for(int g = 0 ; g <= 1 ; g++){
                int s = a + b + c + d + e + f + g;
                if(s == 1){
                  ans++;
                }
                if(s >= 2){
                  //当相连的二极管任何一个都是不亮时continue
                  if(a == 1 && f ==0 && b ==0){
                    continue;
                  }
                  else if(b == 1 && a == 0 && g ==0 && c == 0){
                    continue;
                  }
                  else if(c == 1 && b == 0 && g == 0 && d == 0){
                    continue;
                  }
                  else if(d == 1 && e == 0 && c == 0){
                    continue;
                  }
                  else if(e == 1 && f == 0 && g == 0 && d == 0){
                    continue;
                  }
                  else if(f == 1 && a == 0 && g == 0 && e == 0){
                    continue;
                  }
                  else if(g == 1 && f == 0 && b == 0 && e == 0 && c== 0){
                    continue;
                  }
                  ans++;
                }
              }
            }
          }
        }
      }
    }
  }
  //结果-3 是因为当二极管两两成组的时候有3种不是连起来的情况:ab与ed,af与cd,ef与cb
  printf("%d",ans-3);
  // 请在此输入您的代码
  return 0;
}

 持续更新......

有帮助请来个👍喔!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

تچ快乐杂货店يچ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值