蓝桥杯 C++项目题库5

3.3白皮书初级组模拟题 2
3.3.1 求和
输入一个正整数 N(1<N<20000),输出 1 到 N 之间所有正整数的和(包含 1
和 N)。
输入描述:输入一个正整数 N(1<N<20000)。
输出描述:输出 1 到 N 之间所有正整数的和(包含 1 和 N)。
【样例输入】3
【样例输出】6
#include<iostream>
using namespace std;
int main() {
int n, i, sum = 0;
cin >> n;
for (i = 1; i <= n; i++) {
sum = sum + i;
}
cout << sum;
第 92 页 共 256 页
return 0;
}
3.3.2 统计次数
输入一段英文(包含字母和“.”),分别统计出这段英文字符串共有多少个字符
(包含字母和“.”)及“.”出现的次数。
输入描述:输入一段英文字符串(字符串长度<100)。
输出描述:第一行输出字符总个数;第二行输出“.”在这段英文字符串中出现的次
数。
【样例输入】
aaa. 【样例输出】
4
1
方法一、理解题目为 一段英文只包含字母和“.”。
#include<iostream>
#include<cstring>
using namespace std;
int main() {
string s;
cin >> s; //不能完整读入带空格字符串
int len, cnt = 0;
len = s.size();
for (int i = 0; i < len; i++) {
if (s[i] == '.') {
cnt++;
}
}
cout << len << endl << cnt;
return 0;
}
//方法二、考虑输入内容不仅仅包含字母和“.”:
#include<iostream>
#include<cstring>
第 93 页 共 256 页
using namespace std;
int main() {
string s;
getline(cin, s);
int len, cnt1 = 0, cnt2 = 0;
len = s.size();
for (int i = 0; i < len; i++) {
if ((s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= 'a' && s[i] <= 'z')) {
cnt1++;
}
if (s[i] == '.') {
cnt2++;
}
}
cout << cnt1 + cnt2 << endl;
cout << cnt2;
return 0;
}
3.3.3 排序
连续输入 5 个正整数(0<正整数<1001),正整数之间以一个空格隔开,然后
将这五个正整数按照从大到小的顺序输出(输出的正整数之间以一个英文逗号隔开)。
输入描述:连续输入 5 个正整数(0<正整数<1001)分别以一个空格隔开。
输出描述:按照从大到小的顺序输出且每个正整数之间用一个英文逗号隔开。
【样例输入】
3 2 5 5 4
【样例输出】
5,5,4,3,2
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int a[5];
for (int i = 0; i < 5; i++) {
cin >> a[i];
第 94 页 共 256 页
}
sort(a, a + 5); //默认从小到大排序
cout << a[4]; //先输出第一个数前面没有分隔符
for (int i = 3; i >= 0; i--)
cout << "," << a[i];
return 0;
}
3.3.4 最大公约数 最小公倍数
1、倍数与约数:如果 a 能被 b 整除,a 就叫做 b 的倍数,b 就叫做 a 的约数。
约数和倍数都表示一个整数与另一个整数的关系,不能单独存在。
2、最大公约数:几个整数中公有的约数,叫做这几个数的公约数;其中最大的一个,
叫做这几个数的最大公约数。举例:12、16 的公约数有 1、2、4,
其中最大的一个是 4,所以 4 是 12 与 16 的最大公约数。
3、最小公倍数:几个自然数公有的倍数,叫做这几个数的公倍数,其中最小的一个,
叫做这几个数的最小公倍数。举例:4 的倍数有 4、8、12、16,……,
6 的倍数有 6、12、18、24,……,4 和 6 的公倍数有 12、24,……,其中最小的
是 12,所以 4 和 6 最小公倍数为 12。
分别输入两个正整数(1<正整数<201),输出这两个正整数的最大公约数 M 及最
小公倍数 N(注:M 和 N 输出到一行,之间以一个英文逗号隔开)。
输入描述:第一行输入第一个正整数;第二行输入第二个正整数。
输出描述:输出这两个正整数的最大公约数 M 及最小公倍数 N(M 和 N 输出
到一行,之间以一个英文逗号隔开)。
【样例输入】
4
6
【样例输出】
2,12
方法一:先求最小公倍数
#include <iostream>
#include <cmath>
using namespace std;
int main() {
int m, n, i = 1, gbc;
cin >> m >> n;
第 95 页 共 256 页
if (m < n)
swap(m, n);
while (m * i % n != 0) {
i++;
}
gbc = m * i;
cout << m*n / gbc << "," << gbc;
//根据公式计算 最大公约数=两整数的乘积 ÷最小公倍数
//注意要用括号改变计算优先级
return 0;
}
方法二:辗转相除法 求最大公约
#include<iostream>
using namespace std;
int gys(int x, int y) { //辗转相除法
if (y == 0) {
return x;
}
return gys(y, x % y);
}
int main() {
int n, m;
cin >> n >> m;
cout << gys(n, m) << ',' << n*m / a(n, m);
return 0;
}
3.4白皮书中级组模拟题 2
3.4.1 求和
输入一个正整数 N(N<100),输出 1 到 N(包含 1 和 N)之间所有奇数的
和。
输入描述:输入一个正整数 N(N<100)。
输出描述:输出 1 到 N 之间所有奇数的和。
第 96 页 共 256 页
【样例输入】
3
【样例输出】
4
#include<iostream>
using namespace std;
int main() {
int n, i, sum = 0;
cin >> n;
for (i = 1; i <= n; i = i + 2) {
sum = sum + i;
}
cout << sum;
return 0;
}
3.4.2 求平方
平方是一种运算,比如:a 的平方表示 a×a。
例如:2 的平方为 4(也就是 2*2 的积)。
例如:4 的平方为 16(也就是 4*4 的积)。
输入一个正整数 N(N<30),输出 1 到 N(包含 1 和 N)之间所有正整数的平
方,且所输出的平方数之间以英文逗号隔开。
输入描述:输入一个正整数 N(N<30)。
输出描述:输出 1 到 N 之间所有正整数的平方数,且所输出的平方数之间以英文逗
号隔开。
【样例输入】
3
【样例输出】
1,4,9
#include<iostream>
using namespace std;
int main() {
int i, n;
cin >> n;
for (i = 1; i <= n; i++)
第 97 页 共 256 页
if (i == 1) cout << 1; //逗号的处理
else cout << "," << i*i;
return 0;
}
3.4.3 数位递增数
一个正整数如果任何一个数位小于等于右边相邻的数位,则称为一个数位递
增数。
例如:
1135 是一个数位递增数。
1024 不是一个数位递增数。
输入一个正整数 n(10<n<10001),输出 10 到 n (包含 10 和 n)中有多少个
数位递增数。
输入描述:输入一个正整数 n(10<n<10001)。
输出描述:输出 10 到 n 中有多少个数位递增数。
【样例输入】
15
【样例输出】
5
【上述输入输出样例的进一步解释】
用户输入的正整数,即样例输入为 15,10 到 15 之间的数位递增数有:11、
12、13、14、15。所以样例输出为 5。
#include<iostream>
using namespace std;
int main() {
int n, cnt = 0;
int g, s, b, q;
cin >> n;
//10<n<10001 n 包含 10000 但不符合条件 所以最大枚举 9999 四位数
for (int i = 10; i <= n; i++) {
g = i % 10;
s = i / 10 % 10;
b = i / 100 % 10; //两位数 b=0 不影响判断
q = i / 1000 % 10;
if (g >= s && s >= b && b >= q) {
第 98 页 共 256 页
cnt++;
}
}
cout << cnt;
return 0;
}
3.4.4 最短距离(蛇形填数)
有一个居民小区的楼房全是一样的,并且按矩阵样式排列。其楼房的编号为
1,2,3...,当排满一行时,从下一行相邻的楼往反方向排号。
例如:小区为 3 行 6 列,矩阵排列方式:
要求:已知小区楼房有 w 列及两个楼房楼号 m 和 n,求从 m 号楼到 n 号楼之
间的最短路线经过几个楼(不能斜线方向移动)。
例如上图:当 w=6,m=8,n=2,从 8 号楼到 2 号楼最短的路线经过 5,4,
3,2 四个楼(9,10,11,2 也经过四个楼),故最短路线为 4(注:不考虑
路线只考虑最短路线经过几个楼)。
输入三个正整数 w(1<w<21),m(1<m<10001),n(1<n<10001),且 m 不
等于 n。三个正整数之间以一个空格隔开,输出 m 到 n 的最短路线经过几个
楼。
输入描述:在一行输入三个正整数 w,m,n,三个正整数之间以一个空格隔
开。
输出描述:输出 m 到 n 的最短路线经过几个楼。
【样例输入】
6 8 2
【样例输出】
4
第 99 页 共 256 页
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int a[30][30];
int main(){
int w,m,n,s=1,x1,y1,x2,y2;
cin>>w>>m>>n;
for(int i=1;i<=w;i++){
if(i%2!=0){
for(int j=w;j>=1;j--){
a[i][j]=s++;
}
}else{
for(int j=0;j<w;j++){
a[i][j]=s++;
}
}
}
for(int i=1;i<=w;i++){
for(int j=1;j<=w;j++){
if(a[i][j]==m){
第 100 页 共 256 页
x1=i;
y1=j;
}
if(a[i][j]==n){
x2=i;
y2=j;
}
}
}
cout<<abs((x1+y1)-(y1+y2))+1;
return 0;
}
#include<bits/stdc++.h>
using namespace std; //6 20 80
int main() {
int w,m,n,k=1,L;
int i,j,i1=0,j1=0,i2=0,j2=0;
cin >> w>>m>>n;
L=max(m,n)/w+1;
int a[w+1][L+1]={};
for(i=1;i<=L;i++){
for(j=1;j<=w;j++){
if(i%2==1){
第 101 页 共 256 页
a[i][j]=(i-1)*6+j;
}
else
{
a[i][j]=i*6+1-j;
}
}
}
for(i=1;i<=L;i++){
for(j=1;j<=w;j++){
if(a[i][j]==m){
i1=i;j1=j;
}
if(a[i][j]==n){
i2=i;j2=j;
}
}
}
cout<< i1<<" "<<j1<<endl;
cout<< i2<<" "<<j2<<endl;
cout<<abs(i2-i1)+abs(j2-j1);
return 0;
}
第 102 页 共 256 页
3.4.5 组合
输入两个正整数 m 和 n(20≥m≥n>0),要求 m 个正整数相加的和为 n,输出
满足这个条件的正整数组合有多少。
输入描述:分行输入 m 和 n(20≥m≥n>0)。
输出描述:输出满足这个条件的正整数组合有多少。
【样例输入】
4
8
【样例输出】
5
【上述输入输出样例的进一步解释】
用户输入的两个正整数,即样例输入为 4 和 8,满足条件的有:5+1+1+1=8、
4+2+1+1=8、3+3+1+1=8、3+2+2+1=8、2+2+2+2=8(每组组合都由 4 个正整数
组成且 4 个正整数的和等于 8)所以样例输出为 5。
#include <iostream>
using namespace std;
int a[10001]={1},m,n,total;
int search(int s,int t){
int i;
for(i=a[t-1];i<=s;i++){
if(i<=m){
a[t]=i;
s-=i;
if(s==0&&t==n){
total++;
}
第 103 页 共 256 页
else{
search(s,t+1);
}
s+=i;
}
}
}
int main(){
cin>>n>>m;
search(m,1);
cout<<total;
return 0;
}
第 104 页 共 256 页
3.5***第十届蓝桥青少组省赛 C++高级组
3.5.1 水下探测器
水下探测器可以潜入湖中在任意水深进行科学探索。
湖水的最大深度为 h 米,即它在湖底时到水面的距离,0<=h<=100;
探测器最初的水下深度为 s 米,0<=s<=100;
当探测器不在水面(当前深度大于 0)时,每个 u 指令可使它上浮 1 米,而当
探测器在水面时,u 指令是无效的;
当探测器不在湖底(当前深度小于 h)时,每个 d 指令可使它下沉 1 米,而当
探测器在湖底时,d 指令是无效的;
在执行到无效指令时,探测器不做任何操作而继续执行下一指令。
编程实现:
根据给定的 h、s 和一个指令序列(由字符 u、d 组成的字符串,长度不超过 100),
求出执行完整的指令序列后,探测器的水下深度。
输入:
第一行:h 和 s,以空格分开。0<=s<=h<=100
第二行:长度不超过 100 的指令字符串,串中仅包含字母 u 或 d
输出:
代表探测器在执行指令后的水下深度的数字。
样例输入:
9 1
uduudd
样例输出:
2
考察知识:
基础语法,字符串,循环,条件判断
#include <iostream>
using namespace std;
int main(){
int h,s;
string str;
cin>>h>>s>>str;
for(int i=0;i<str.size();i++){
第 105 页 共 256 页
if(str[i]=='u'&&s>0) s--;
if(str[i]=='d'&&s<h) s++;
}
cout<<s;
}
3.5.2 小猫吃鱼
明明家从 1 号站点出发,开车去旅游,一共要经过 n 个站点,依次为 2、3……n。
由于明明带上了心爱的小猫,在每个站点都要为小猫提供一条鱼用做美餐(包括 1
号站点)。
除了 1 号站点只能吃 1 号站点买的鱼,其他站点既可以吃当地买的鱼,也可吃
之前经过的站点买了存入车载冰箱中的鱼。但车载冰箱消耗的电能来自汽油,所以每
条鱼用冰箱保存到下一站的费用与各个站点的汽油价格有关。
为使问题简化,我们约定:
(1)车从某站开出时油箱中都是此站点刚加的汽油。
(2)车载冰箱能容纳一路上需要的所有鱼。 即:每条鱼的费用既包括购买时的
费用,也包括用冰箱保存鱼的费用。
编程实现:
为了降低小猫吃鱼的总代价,明明预先上网查到了这 n 个站点的鱼价和汽油价
格。并据此算出每个站点买一条鱼的费用以及从该站点到下一站用冰箱保存一条鱼的
费用。你能帮明明算出这一路上小猫吃鱼的最小总费用吗?
输入:
第一行:站点数 n,1<n<100。
接下来的 n 行:每行两个以空格分隔的正整数,表示:这一站买一条鱼的费用,
以及从这一站把每条
鱼保存到下一站的费用,两个费用均为小于 10000 的正整数。
输出:
最小总费用,是一个正整数。
样例输入:
5
6 3
7 1
3 2
8 3
9 5
样例输出:
第 106 页 共 256 页
29
使用 for 循环,每次看看价钱是不是最划算,不是就加上一条鱼,是也要加上这
一条鱼,每次还要加上保存的价钱。
#include <iostream>
using namespace std;
int main() {
int n;
cin>>n;
int m1[n], m2[n];
for(int i = 0; i < n; i++)
cin>>m1[i]>>m2[i];
//输入当前买鱼的钱和保存的钱
int min = 9999999, t = 0;
for(int i = 0; i < n; i++) {
if(min > m1[i])
min = m1[i];
t = t + min; //上一条鱼
min = min + m2[i]; //保存
}
cout<<t<<endl;
return 0;
}
3.5.3 评选最佳品牌
n 个评委投票,在 m 个商品中评选一个最佳品牌。
评选采用多轮淘汰制,即:每轮投票,淘汰掉得票最少的候选品牌(得票并列最
少的品牌一起淘汰)。
如此一轮轮淘汰下去,如果最后只剩下一个品牌当选,即告评选成功。
但如果在某轮投票中,当时未被淘汰的所有候选品牌(大于等于两个品牌)都并
列得票最少,即告评选失败。
如果评选成功就输出当选品牌号。否则输出最后一轮评选时唯一选票数的相反数。
在评选流程中,每个评委的态度都可用一个序列来表示;例如当 m=5 时,某评
委的评选态度序列为:3、
5、1、2、4,则表示该评委:优先投 3 号,当 3 号被淘汰时投 5 号,当 3 和 5
都被淘汰时投 1,当 3、5、1 都被淘汰时投 2,仅剩 4 号时才投 4 号品牌的票。
选票的序列中可以表示弃权,用 0 来表示,例如当 m=5 时,某评委的评选态度
序列为:3、5、0,则表示该评委:优先投 3 号,当 3 号被淘汰时投 5 号,其它情
第 107 页 共 256 页
况下不投任何品牌的票。
编程实现:
请你编一个程序,模拟各轮投票的过程,得到评选结果。
输入:
第一行:m(0<m<10,表示参加评选的品牌数)和 N(1<n<1000,表示参加投票的评委
数),之间以空格分隔接下来的 n 行:每行都是长度不超 m 的数字字符串,每个字
符串表示一个评委的评选态度。
输出:
评选结果。
样例 1 输入:
3 4
123
213
132
10
样例 1 输出:
1
样例 2 输入:
3 4
321
213
231
312
样例 2 输出:
-2
样例数据分析:
样例 1:
第一行 3 4 代表 3 个品牌,4 个评委
第一轮投票,3 个评委优先选择 1 号品牌,1 个评委选择 2 号品牌,品牌 3 得票最少, 淘汰掉
第二轮投票,3 个评委优先选择 1 号品牌,1 个评委选择 2 号品牌,品牌 2 得票最少, 淘汰掉,淘汰 2 号品牌后,只剩一个 1 号品牌,1 号品牌胜出,最终结果 1
样例 2:
第一行 3 4 代表 3 个品牌,4 个评委
第一轮投票,2 个评委选择 2 号品牌,两个评委选择 3 号品牌,1 号得票最少,淘汰掉
第二轮投票,2 个评委选择 2 号品牌,两个评委选择 3 号品牌,由于只剩下两个品牌,
第 108 页 共 256 页
且并列最少,都是 2 票,代表评选失败,需要输出最后一轮票数 2 的相反数-2
最终结果 -2
考察知识:
字符串,桶排序,模拟算法
#include <iostream>
using namespace std;
int main(){
int m,n;
cin>>m>>n;
string str[n+1];
for(int i=1;i<=n;i++){
cin>>str[i];
}
int a[m+1];//记录投票过程,-1 代表淘汰
while(true){
for(int i=1;i<=m;i++){
//重新计票,所有没有被淘汰的票数归零
if(a[i]!=-1)a[i]=0;
}
for(int i=1;i<=n;i++){
//计票
string s=str[i];
for(int j=0;j<s.size();j++){
char t=s[j]-'0';
if(t==0){
//如果为 0 说明弃权
break;
}else{
//不为 0,则代表要给 t 投票,如果 t 没有被淘汰则给它投票
if(a[t]>=0){
a[t]=a[t]+1;
break;
}
}
}
}
第 109 页 共 256 页
int min=m+1;
int max=0;
for(int i=1;i<=m;i++){
if(a[i]>=0){
if(min>a[i]) min=a[i];
if(max<a[i])max=a[i];
}
}
if(max>min){
//最大值比最小值大,需要将所有最小值的淘汰
for(int i=1;i<=m;i++){
if(a[i]==min)a[i]=-1;
}
}else{
//最大值和最小值相等说明平票
int count=0;
int dx=0;
for(int i=1;i<=m;i++){
if(a[i]==max){
count++;
dx=i;
}
}
if(count>1){
//如果数量多,说明评选失败
cout<<0-max;
}else{
cout<<dx;
}
break;
}
}
cin>>m;
}
第 110 页 共 256 页
3.5.4 蓝桥杯赛迷宫
把一个 n 行 m 列的字符阵列看做一个迷宫,迷宫仅包含 L、Q、B、S 中的大
写字母(蓝桥杯赛的汉语拼音首字母)。
初始时,你可以从任意一个“L”字母开始,移向相邻的“Q”字母,然后从此“Q”字
母出发,移向相邻的“B”字母,然后从此“B”字母出发,移向相邻的“S”字母……。这
样,你就算是走过了一个“LQBS”字符序列。
接下来,仍然可以从此“S”字母出发,移向相邻的“L”字母……,重复上述的动作,
你就可以不断地走过“LQBS”序列。
请注意,所谓相邻仅包含上、下、左、右 4 个方向,且只能从 L->Q,从 Q->B,
从 B->S,从 S->L。
可以想像,由于选择的出发点不同,我们有可能在迷宫中走过无数次的“LQBS”,
或者是有限次的“LQBS”,
或者一次也走不了。
编程实现:
请你编写程序,求出在给定的迷宫中,我们最多可以走过多少次“LQBS”?
输入:
第一行:正整数 n,m,表示迷宫的规模为 n 行 m 列,0<m<100,0<n<100
接下来的 n 行:每行 m 个符合题意的字母,字母间无空格。
输出:
一个整数。即:如果在迷宫中可以无限次的走过“LQBS”,输出-1,否则,输出可
以走过“LQBS”的最多次数。
样例 1 输入:
1 2
LQ
样例 1 输出:
0
样例 2 输入:
3 3
LSB
QBQ
BSL
样例 2 输出:
-1
样例 3 输入:
4 4
第 111 页 共 256 页
BLQB
BBQS
SBQL
QQQQ
样例 3 输出:
2
样例数据分析:
样例 1:
第一行数据 3 3 代表是 3 行 3 列的迷宫
第 1 步,寻找 L
LSB
QBQ
BSL
第 2 步,在 L 的上下左右寻找 Q
LSB
QBQ
BSL
第 3 步,在 Q 的上下左右寻找 B
LSB
QBQ
BSL
第 4 步,在 B 的上下左右寻找 S
LSB
QBQ
BSL
如此当重复到 10 次的时候,仍可以继续走,代表进入无限循环
因为 3 行 3 列最多 9 个格子,能走 10 步就代表一定进入无限循环
输出-1
样例 2:
第一行数据 4 4 代表是 4 行 4 列的迷宫
第 1 步,寻找起点 L
BLQB
BBQS
SBQL
QQQQ
第 2 步,在 L 的上下左右寻找 Q
第 112 页 共 256 页
BLQB
BBQS
SBQL
QQQQ
第 3 步,在 Q 的上下左右寻找 B
BLQB
BBQS
SBQL
QQQQ
第 4 步,在 B 的上下左右寻找 S
BLQB
BBQS
SBQL
QQQQ
第 5 步,在 S 的上下左右寻找 L
BLQB
BBQS
SBQL
QQQQ
第 6 步,在 L 的上下左右寻找 Q
BLQB
BBQS
SBQL
QQQQ
第 7 步,在 Q 的上下左右寻找 B
BLQB
BBQS
SBQL
QQQQ
第 8 步,在 B 的上下左右寻找 S
BLQB
BBQS
SBQL
QQQQ
第 9 步,在 S 的上下左右寻找 L
因为找不到 L 了,则代表迷宫走到尽头,一共走了 8 步,LQBS 一共 4 个字符,所以走
第 113 页 共 256 页

8/4=2 共计 2 次 LQBS,输出 2
考察知识:
搜索与回朔
未学到搜索与回朔算法,可以采用循环遍历类似穷举算法进行题解
#include<iostream>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
char map[n+1][m+1];
int path[n+1][m+1];
for(int i=1;i<=n;i++){
string s;
cin>>s;
for(int j=1;j<=m;j++){
map[i][j]=s[j-1];
path[i][j]=0;
if(map[i][j]=='L'){
path[i][j]=1;
}
}
}
string LQBS="LQBS";
int now=1;
while(true){
int flag=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(path[i][j]==now){
if(map[i][j-1]==LQBS[now%4]){
path[i][j-1]=now+1;
flag++;
}
if(map[i][j+1]==LQBS[now%4]){
第 114 页 共 256 页
path[i][j+1]=now+1;
flag++;
}
if(map[i-1][j]==LQBS[now%4]){
path[i-1][j]=now+1;
flag++;
}
if(map[i+1][j]==LQBS[now%4]){
path[i+1][j]=now+1;
flag++;
}
}
}
}
/*for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<path[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;*/
if(flag==0){
break;
}
if(now>(n+1)*(m+1)){
break;
}
now++;
}
if(now>(n+1)*(m+1)){
cout<<-1;
}else{
cout<<now/4;
}
cin>>n;
}
第 115 页 共 256 页
3.5.5 最大购物优惠
小惠听说超市正在打折促销,要制订一个得到最大优惠的购物计划。
小惠的体力可以提起 w 单位重量的东西,还有一个能装 V 个单位体积的购物
袋,并详细了解了各打折商品的重量、体积及此商品实际优惠的金额。她想在自己体
力的限度和购物袋容积限度内,尽可能多地得到购物优惠。
超市规定这些打折商品每种只能购买一件。
编程实现:
请你编写程序,制定一个购买商品的计划,求出小惠能得到的最大优惠金额和实
际应购买的各商品序号。
输入:
第一行:依次为 w、v 和 n(n 为商品种类数),所有数值均为不超过 100 的正整
数 接下来的 n 行:每行有三个整数,依次为某种商品的重量、体积和让利金额,数
值间以空格分开,所有数值均为不超过 100 的正整数
输出:
第一行:小惠能够得到的最大让利金额
第二行:依次为从小到大排列的商品序号,序号从 1 开始,序号间用空格分开。
若第二行输出的序列
不唯一,则输出其最小字典序。
样例输入:
10 9 4
8 3 6
5 4 5
3 7 7
4 5 4
样例输出:
9
2 4
考察知识:
动态规划,二维费用的背包问题,在 01 背包问题的基础上增加一个费用维度
状态转移方程:
yh[i][j][k]=max(yh[i-1][j][k],yh[i-1][j-w[i]][k-v[i]]+n[i])
经典 01 背包问题解
第 116 页 共 256 页
#include <iostream>
using namespace std;
int main() {
int w, v, n;
cin >> w >> v >> n;
int a[n + 1], b[n + 1], c[n + 1];
int yh[n + 1][w + 1][v + 1];
string s[n + 1][w + 1][v + 1];
for (int i = 1; i <= n; i++)
cin >> a[i] >> b[i] >> c[i];
for (int i = 0; i <= n; i++) {
for (int j = 0; j <= w; j++) {
for (int k = 0; k <= v; k++) {
yh[i][j][k] = 0;
s[i][j][k] = "";
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= w; j++) {
for (int k = 1; k <= v; k++) {
int bn = yh[i - 1][j][k];
int n = 0;
if (j >= a[i] && k >= b[i]) { //重量和体积够,拿当前物品
n = yh[i - 1][j - a[i]][k - b[i]] + c[i];
}
if (n > bn) { //如果拿了比不拿价值大,就拿这个物品
yh[i][j][k] = n;
//同时记录拿了这个物品
s[i][j][k] = s[i - 1][j - a[i]][k - b[i]] + " " + (char)(i + '0');
} else {
//否则记录当前重量和体积的最优策略是不拿
yh[i][j][k] = bn;
//同时记录不拿当前物品,保持和之前一样的物品列表
s[i][j][k] = s[i - 1][j][k];
第 117 页 共 256 页
}
}
}
}
cout << yh[n][w][v] << endl;
string str = s[n][w][v];
cout << str.substr(1, str.size() - 1);
}
3.5.6 购物单
XX 大促销又来了,长长的购物单,都是有打折优惠的。
请你帮他计算一下,需要从取款机上取多少现金,才能搞定这次购物。
取款机只能提供 100 元面额的纸币。小明想尽可能少取些现金,够用就行了。
你的任务是计算出,小明最少需要取多少现金。
180.90 88 折
10.25 65 折
56.14 9 折
104.65 9 折
100.30 88 折
297.15 半价
26.75 65 折
130.62 半价
#include<iostream>
using namespace std;
int main()
{
double j,z,sum=0;//原价 折扣
for(int i=1; i<=8; i++) {
cin>>j>>z;
sum=sum+j*z;
}
sum=sum+0.9; //零钱部分舍入 精确到 1 角
if(int(sum)%100>0)//不是 100 元的整数倍
cout<<int(sum)/100*100+100;
else
cout<<int(sum);
第 118 页 共 256 页
return 0;
}
3.5.7 等差素数列
2,3,5,7,11,13,....是素数序列。类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫
等差素数数列。上边的数列公差为 30,长度为 6。
2004 年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。
这是数论领域一项惊人的成果!有这一理论为基础,请你借助手中的计算机,满
怀信心地搜索:
长度为 10 的等差素数列,其公差最小值是多少?
注意:需要提交的是一个整数,不要填写任何多余的内容和说明文字。
先用埃氏筛法,把 1~N (N 先设置一个 10000 吧,不够再加)以内的素数都筛选出
来,然后再枚举 1~10000(公差,不够再加),寻找连续 10 个的素数。
#include <iostream>
using namespace std;
const int maxn = 10000000;
int prime[maxn];
bool is_prime[maxn + 10]; //is_prime[i]为 true 表示 i 是素数
bool is_Prime(int n)
{
int i = 0;
for (i = 2; i * i <= n; i++)
{
if (n % i == 0) return false;
}
return n != 1;
}
//返回 n 以内的素数
int sieve(int n)
{
int p = 0;
//初始化
for (int i = 0; i <= n; i++) {
is_prime[i] = true;
}
is_prime[0] = is_prime[1] = false;
第 119 页 共 256 页
for (int i = 0; i <= n; i++)
{
if (is_prime[i])
{
prime[p++] = i; //将素数添加到 prime 中
//1.首先 2 是素数, 然后划去所有 2 的倍数
//2.表中剩余的最小数字是 3, 他不能被更小的数整除,所以是素数
//再将表中所有 3 的倍数都划去
//3.以此类推, 如果表中剩余的最小数字是 m 时,m 就是素数。然后将表
中所有 m 的倍数都划去
for (int j = 2 * i; j <= n; j += i) {
is_prime[j] = false;
}
}
}
return p;
}
void solve(){
int N = 10000;
int cnt = sieve(N);
//公差
for (int d = 10; d < N; d++){
//枚举 N 以内所有素数
for (int i = 0; i < cnt; i++){
int tmp = prime[i],
flag = true;
//是否连续 10 个都为素数
for (int j = 0; j < 9; j++)
{
if (tmp + d > N || !is_Prime(tmp + d))
{
flag = false;
第 120 页 共 256 页
break;
}
else
{
tmp += d; //下一个素数
}
}
if (flag) {
cout << d << " " << prime[i] << endl;
return;
}
}
}
}
int main()
{
solve();
return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值