蓝桥杯-数学知识和简单动态规划专题1(包含历年蓝桥杯真题和详细注释)

目录

买不到的数目(第四届蓝桥杯省赛C++A组,第四届蓝桥杯省赛JAVAC组)

 蚂蚁感冒(第五届蓝桥杯省赛C++A/B组)

 饮料换购(第六届蓝桥杯省赛C++A/C组,第六届蓝桥杯省赛JAVAB组)

背包问题


买不到的数目(第四届蓝桥杯省赛C++A组,第四届蓝桥杯省赛JAVAC组)

小明开了一家糖果店。

他别出心裁:把水果糖包成4颗一包和7颗一包的两种。

糖果不能拆包卖。

小朋友来买糖的时候,他就用这两种包装来组合。

当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。

你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。

大于17的任何数字都可以用4和7组合出来。

本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。

输入格式

两个正整数 n,mn,m,表示每种包装中糖的颗数。

输出格式

一个正整数,表示最大不能买到的糖数。

数据范围

2≤n,m≤10002≤n,m≤1000,
保证数据一定有解。

输入样例:

4 7

输出样例:

17
#include<iostream>
using namespace std;
int p,q;
int main()
{
    cin>>p>>q;
    cout<<p*q-p-q<<endl;//(p-1)(q-1)-1 打表找规律 
    return 0;
}

 蚂蚁感冒(第五届蓝桥杯省赛C++A/B组)

长 100100 厘米的细长直杆子上有 nn 只蚂蚁。

它们的头有的朝左,有的朝右。

每只蚂蚁都只能沿着杆子向前爬,速度是 11 厘米/秒。

当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。

这些蚂蚁中,有 11 只蚂蚁感冒了。

并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。

请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

输入格式

第一行输入一个整数 nn, 表示蚂蚁的总数。

接着的一行是 nn 个用空格分开的整数 XiXi, XiXi 的绝对值表示蚂蚁离开杆子左边端点的距离。

正值表示头朝右,负值表示头朝左,数据中不会出现 00 值,也不会出现两只蚂蚁占用同一位置。

其中,第一个数据代表的蚂蚁感冒了。

输出格式

输出1个整数,表示最后感冒蚂蚁的数目。

数据范围

1<n<501<n<50,
0<|Xi|<1000<|Xi|<100

输入样例1:

3
5 -2 8

输出样例1:

1

输入样例2:

5
-10 8 -20 12 25

输出样例2:

3
#include<iostream>
using namespace std;
const int N = 55;
int n;
int x[N];
//本题重要思想 两只蚂蚁碰撞掉头 可以等价于两只蚂蚁穿过 
//在转换思想后:在第一只蚂蚁左边的往左的蚂蚁一定不会被感染 在第一只蚂蚁右边往右走的蚂蚁一定不会被感染 

/* 第一只蚂蚁向右时
在第一只蚂蚁右边往左的蚂蚁一定会被感染 如果第一只蚂蚁右边向左的蚂蚁存在的话 那么第一只蚂蚁左边向右走的蚂蚁一定被感染 
如果第一只蚂蚁右边向左的蚂蚁不存在的话 那么第一只蚂蚁左边向右走的蚂蚁不会被感染 
*/

/*第一只蚂蚁向左时
在第一只蚂蚁左边往右走的蚂蚁一定会被感染 如果第一只蚂蚁左边向右的蚂蚁存在的话 那么第一只蚂蚁右边向左走的蚂蚁一定被感染 
如果第一只蚂蚁左边向右的蚂蚁不存在的话 那么第一只蚂蚁右边向左走的蚂蚁一定不会被感染 
*/

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)cin>>x[i];
    int l=0,r=0;//表示在第一只蚂蚁左边从左往右走的蚂蚁 和第一只蚂蚁右边从右往左走的蚂蚁
    for(int i=1;i<n;i++)
    {
        if(abs(x[i])>abs(x[0])&&x[i]<0)r++;//在第一只蚂蚁右边从右往左走的蚂蚁
        else if(abs(x[i])<abs(x[0])&&x[i]>0)l++;//在第一只蚂蚁左边从左往右走的蚂蚁
    }
    //第一只蚂蚁向右时,第一只蚂蚁右边向左的蚂蚁不存在的话 或者  第一只蚂蚁向左时 如果第一只蚂蚁左边向右的蚂蚁不存在的 就第一只蚂蚁被感染
    if((x[0]>0&&r==0)||(x[0]<0&&l==0))cout<<1<<endl;
    else cout<<l+r+1<<endl;// 左边向右的蚂蚁 + 右边向左的蚂蚁 +第一只蚂蚁
    return 0;
    
    
}

 饮料换购(第六届蓝桥杯省赛C++A/C组,第六届蓝桥杯省赛JAVAB组)

有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。

第 ii 件物品的体积是 vivi,价值是 wiwi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n;
//简单模拟题
int main()
{
    cin>>n;
    int ans=n;//ans表示答案 首先先将n瓶加入答案
    while(n>=3)//当n大于等于3的时候 表示还可以再继续兑换
    {
        int t=n/3;//表示可以最多兑换的瓶数
        n=n-(t*3)+t;//n减去消耗的饮料数 在加上兑换来的饮料
        ans+=t;//答案加上兑换来的饮料
    }
    cout<<ans<<endl;
    return 0;
}

背包问题

有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。

第 ii 件物品的体积是 vivi,价值是 wiwi。

求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。

输入格式

第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。

接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。

输出格式

输出一个整数,表示最大价值。

数据范围

0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000

输入样例

4 5
1 2
2 4
3 4
4 5

输出样例:

8
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int dp[N][N];//dp[i][j]表示前i个物品 总体积是j最大价值
int v[N],w[N];//v 体积 w 价值
int n,m;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>v[i]>>w[i];
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<=m;j++)
        {
            dp[i][j]=dp[i-1][j];//不选第i个物品 前i-1个物品最大价值
            if(j>=v[i])dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]]+w[i]);//当体积大于v[i] 可以选择选第i个物品 
        }
    }
    int ans=0;
    for(int i=0;i<=m;i++)ans=max(ans,dp[n][i]);//获取最大的答案 
    cout<<dp[n][m]<<endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值