slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
第 3 章 C++ 中的条件与循环 PowerPoint Presentation
Download Presentation
第 3 章 C++ 中的条件与循环

Loading in 2 Seconds...

play fullscreen
1 / 68

第 3 章 C++ 中的条件与循环 - PowerPoint PPT Presentation


  • 159 Views
  • Uploaded on

第 3 章 C++ 中的条件与循环. 第 3 次见面! acm.nefu.edu.cn/C++_03.ppt. 这 2 天你们 C++ 吗?. 一夜北风寒,万里彤云厚; 长空雪乱飘,改尽江山旧。 仰面观太虚,疑是玉龙斗; 纷纷鳞甲飞,顷刻遍宇宙。 骑驴过小桥,独叹梅花瘦! 谁知道出自 ------ ? 是 李白 吗?. 上次实验课总结. 1 、注意汉字和英文的输入法; 2 、 endl 不是 end1; 3 、时时刻刻使用 C++ 的基本框架.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about '第 3 章 C++ 中的条件与循环' - kane


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

第3章 C++中的条件与循环

第3次见面! acm.nefu.edu.cn/C++_03.ppt

slide2
这2天你们C++吗?
  • 一夜北风寒,万里彤云厚;
  • 长空雪乱飘,改尽江山旧。
  • 仰面观太虚,疑是玉龙斗;
  • 纷纷鳞甲飞,顷刻遍宇宙。
  • 骑驴过小桥,独叹梅花瘦!
  • 谁知道出自------?
  • 是李白吗?
slide3
上次实验课总结
  • 1、注意汉字和英文的输入法;
  • 2、endl 不是 end1;
  • 3、时时刻刻使用 C++的基本框架
slide4
上机调试的心得(授之以渔)
  • 1、哪行出错了
  • 2、提示的字符是啥
  • 3、是不是自己敲错了
  • 4、缺头文件吗?was not declared in this scope
  • 5、结构,大括号,大小写
  • 6、然后才是真的逻辑出错了
slide5
先学习C++实验的在线评测系统
  • 记住网址:
  • acm.nefu.edu.cn
slide9
如何做题
  • 先看题,如 “寻找吕布”这题;
  • description
  • 三国里面吕布第一,赵云第二,典韦、关羽和马超分别是第3、第4和第5名,这是按武将的勇猛值和必杀技值的和来排名的,即武术值=勇猛值+必杀技值,下面给出这5人的勇猛值和必杀值,请你找出吕布的武术值。
slide10
寻找吕布
  • input
  • 输入数据有多组,每组数据2行,第一行是5人的勇猛值,第二行是5人的必杀技值。勇猛值和必杀值是整数哦(32位) output
  • 输出吕布的武术值。
slide11

sample_input

  • 1 2 3 4 5
  • 1 2 3 4 5
  • 20 21 22 45 87
  • 1 100 8 99000 23
  • sample_output
  • 10
  • 99087
  • hint
  • 吕布的勇猛值和必杀技值都是第一的!
slide12

#include <iostream>

  • using namespace std;
  • int main()
  • {
  • int data[6],inp[6];//定义变量
  • int ym,bs;//勇猛值 必杀值的变量
  • while(cin>>data[1]>>data[2]>>data[3]>>data[4]>>data[5])// 注意
  • {
  • ym=0,bs=0; //这句很重要,必须先清0
  • for(int i=1;i<=5;i++) if (ym<data[i]) ym=data[i];
  • cin>>inp[1]>>inp[2]>>inp[3]>>inp[4]>>inp[5];
  • for(int i=1;i<=5;i++) if (bs<inp[i]) bs=inp[i];
  • cout<<ym+bs<<endl;
  • }
  • //cout << “Hello world!” << endl; 记得要注视掉啊
  • return 0;
  • }
slide13
再看服务器里的数据
  • data.in 输入文件 data.out 输出文件
  • 1 2 3 4 5 10
  • 1 2 3 4 5 99087
  • 20 21 22 45 87 16
  • 1 100 8 99000 23
  • 1 2 6 8 9
  • 7 4 3 2 1 你不知道服务器的数据是啥!
slide16
欢迎有敏感的人加入ACM
  • 数学好
  • 算法好(可以培养)
  • 能吃苦就行
slide17
条件语句
  • if
  • switch
  • 和C 语言一样,基本知识不变
  • 通过实例来讲解
slide18
条件表达式
  • ?:运算符 :问号冒号运算符
  • 作用:更加简练的用来表达条件执行的方式
  • 形式 :

(条件) ? 表达式1 : 表达式2

  • 执行过程:首先计算条件值。如果条件结果为true,则计算表达式1的值,并将它作为整个表达式的值。如果条件结果为false,则整个表达式的值为表达式2的值。
slide19
实例
  • 例如将x和y中值较大的一个赋值给max,可以用下列语句:

max = (x > y) ? x : y;

  • ?:运算符用于输出。例如,想输出一个布尔变量flag的值,如果直接用 cout << flag;

那么当flag为“真”时,输出为1;当flag为“假”时,输出为0。

如果我们想让flag为“真”时输出true,为“假”时输出false,可以用if 语句

if (flag) cout << “true”;

else cout << “false”;

看上去太罗嗦。但如果用?:运算符只需要一行

cout << ( flag ? "true" : "false" ) << endl;

slide20
判断闰年的程序

#include <iostream>

using namespace std;

int main()

{ int year;

bool result;

cout << "请输入所要验证的年份:";

cin >> year;

result = (year % 4 == 0 && year % 100 !=0)|| year % 400 == 0;

if (result) cout << year << "是闰年" << endl;

else cout << year << "不是闰年" << endl;

return 0;

}

slide21
计算机自动出四则运算计算题

要求自动出0 - 9之间的四则运算题,并批改结果

生成题目

Switch(题目类型)

{ case 加法:显示题目,输入和的值,判断正确与否

case 减法:显示题目,输入差的值,判断正确与否

case 乘法:显示题目,输入积的值,判断正确与否

case 除法:显示题目,输入商和余数的值,判断正确与否

}

slide22
关键问题
  • 如何让程序每次执行的时候都出不同的题目?
  • 随机数生成器rand():能随机生成0到RAND_MAX之间的整型数
  • 将生成的随机数映射到0 - 9之间:
    • Rand() % 10
    • rand() * 10 / (RAND_MAX + 1)。
  • 运算符的生成:用编码0 - 3表示四个运算符。因此题目的生成就是生成0 - 3之间的随机数。
slide23

12348

rand()

种子

12348

随机数的种子
  • 计算机产生的随机数称为伪随机数,它是根据一个算法计算出来的。
  • 系统为每个程序、每次执行指定的随机数的种子都是相同的,因此程序每次执行生成的随机数序列都是相同的。
slide24
改变随机数的种子
  • 设置种子的函数srand : srand (种子)
  • 如何让程序每次执行时选择的种子都不一样呢?
  • 选择系统时间为种子:time(NULL) 取当前的系统时间。
slide25

自动出题程序

#include <cstdlib> //包含伪随机数生成函数

#include <ctime> //包含取系统时间的函数

#include <iostream>

using namespace std;

int main()

{

int num1, num2, op, result1, result2;

//num1,num2:操作数,op:运算符,result1,result2: 结果

srand(time(NULL)); //随机数种子初始化

num1=rand() * 10 / (RAND_MAX + 1); // 生成运算数 RAND_MAX=32767

num2=rand() * 10 / (RAND_MAX + 1); //生成运算数

op=rand() * 4 / (RAND_MAX + 1);

// 生成运算符 0--+, 1-- -, 2--*,3-- /

slide26

switch (op)

{case 0: cout << num1 << "+" << num2 << "= ?" ; cin >> result1;

if (num1 + num2 == result1) cout << "you are right\n";

else cout << "you are wrong\n";

break;

case 1: cout << num1 << "-" << num2 << "= ?" ; cin >> result1;

if (num1 - num2 == result1) cout << "you are right\n";

else cout << "you are wrong\n";

break;

case 2: cout << num1 << "*" << num2 << "= ?" ; cin >> result1;

if (num1 * num2 == result1) cout << "you are right\n";

else cout << "you are wrong\n";

break;

slide27

case 3: cout << num1 << "/" << num2 << "= ?" ;

cin >> result1;

cout << “余数为 = ?"; cin >> result2;

if ((num1 / num2 == result1)

&& (num1 % num2 == result2))

cout << "you are right\n";

else cout << "you are wrong\n";

break;

}

return 0;

}

slide28
该程序的缺陷
  • 每次执行只能出一道题
  • 减法可能出现负值
  • 除法可能出现除0
  • 结果太单调
slide29
再看循环结构
  • For 基本的习惯
  • While 用处
  • Do while
slide30
For循环实例
  • 某班级有100个学生,设计一程序统计该班级某门考试成绩中的最高分、最低分和平均分。
  • 方案一:先输入100个整型数,保存在各自的变量中。然后依次检查这100个数,找出最大的和最小的。在找的过程中顺便可以把所有的数都加起来。最后将总和除100就得到了平均值。
slide31
方案一的缺陷
  • 需要定义100个变量
  • 需要输入100个变量的值
  • 从100个变量中找出最大者,需要100个if 语句
  • 从100个变量中找出最小者,需要100个if 语句
  • 将这100个变量加起来需要一个长长的算术表达式
slide32
方案二
  • 每个学生的分数在处理过后就没用了,为此,可以用一个变量保存当前正在处理的分数
  • 每次输入分数的同时将它们加起来:70加40等于110,110加80等于190……。并记住最低分的和最高分的值。上述过程重复100次。
slide33
方案二的实现
  • 定义: int value, total,max, min;
  • 当输入每个数值时必须执行下面的步骤,这可以用for循环实现
    • 请求用户输入一个整数值,将它存储在变量value中。
    • 将value加入到保存当前和的变量total中。
    • 如果value大于max,将value存于max。
    • 如果value小于min,将value存于min。
slide34

#include<iostream>

using namespace std;

int main()

{ int value, total, max, min, i;//value:当前输入数据,i为循环变量

total = 0; max = 0; min = 100; //变量的初始化

for (i=1; i<=100; ++i) {

cout << "\n请输入第" << i << "个人的成绩:"; cin >> value;

total += value;

if (value > max) max = value;

if (value < min) min = value;

}

cout << "\n最高分:" << max << endl;

cout << "最低分:" << min << endl;

cout << "平均分:" << total / 100 << endl;

return 0;

}

注意缩进

slide35

a

b

For循环实例
  • 求函数 在区间[a, b]之间的定积分
  • 实现思想:函数与x轴围成的区域的面积。定积分可以通过将这块面积分解成一连串的小矩形,计算各小矩形的面积的和而得到
slide36
int main()

{

double a, b, dlt, integral = 0;

cout << "请输入定积分的区间:" ;

cin >> a >> b;

cout << "请输入小矩形的宽度:" ;

cin >> dlt;

for (double x = a + dlt / 2; x < b; x += dlt)

integral += (x * x + 5 * x + 1) * dlt;

cout << "积分值为:" << integral << endl;

return 0;

}

slide37

eg 2.求

时结束。

ex=0;

p = 1;

while (p>0.000001) {

ex += p;

计算新的p;

}

问题:

如何计算p?计算第i个p,需要两个i次的循环。第一个循环计算xi,第二个循环计算i!

解决方案:

从前一项计算后一项。如果p是第i项的值,则第i+1项的值为 p*x/(i+1)

slide38

int main()

{double ex, x, p;//ex存储ex的值,p保存当前项的值

int i;

cout << "请输入x:"; cin >> x;

ex=0; p=1; i=0;

while (p > 1e-6){

ex += p;

++i;

p = p * x / i;

}

cout << "e的" << x << "次方等于:" << ex << endl;

return 0;

}

slide39
枚举法
  • 对所有可能的情况一种一种去尝试,直到找到正确的答案。
  • 枚举法的实现基础是循环。
slide40
枚举法实例一
  • 用50元钱买了三种水果。各种水果加起来一共100个。西瓜5元一个,苹果1元一个,桔子1元3个,设计一程序输出每种水果各买了几个
  • 它有两个约束条件:
    • 第一是三种水果一共100个;
    • 第二是三种水果一共花了50元
  • 可以按一个约束条件列出所有可行的情况,然后对每个可能解检查它是否满足第二个约束条件 。也可以用第二个约束条件列出所有情况,然后对每个可能解检查它是否满足第一个约束条件 。
slide41

#include <iostream>

using namespace std;

int main()

{ int mellon, apple, orange; //分别表示西瓜数、苹果数和桔子数

for (mellon=1; mellon<10; ++mellon) // 对每种可能的西瓜数

for ( apple=1; apple < 50 - 5 * mellon; ++apple) {

//当西瓜数给定后可能的苹果数

orange = 3*(50-5*mellon-apple); // 剩下的钱全买了桔子

if (mellon+apple+orange == 100){ // 三种水果数之和是否为100

cout << "mellon:" << mellon << ' ';

cout << "apple:" << apple << ' ';

cout << "orange:" << orange << endl;

}

}

return 0;

}

slide42
执行结果

Mellon:1 apple:18 orange:81

Mellon:2 apple:11 orange:87

Mellon:3 apple:4 orange:93

slide43
实例二 — 四大湖问题

上地理课时,四个学生回答我国四大湖的大小时分别说:

甲:洞庭最大,洪泽最小,鄱阳第三

乙:洪泽最大,洞庭最小,鄱阳第二,太湖第三

丙:洪泽最小,洞庭第三

丁:鄱阳最大,太湖最小,洪泽第二,洞庭第三

对于每个湖的大小,每个人仅答对一个,设计一程序让计算机通过这些信息去判别四个湖的大小。

slide44
解题思路
  • 如果用a,b,c,d分别表示四个湖的排序。a表示洞庭湖,b表示洪泽湖,c表示鄱阳湖,d表示太湖。我们可以假设:洞庭最大,洪泽第二,鄱阳第三,太湖第四,然后检查每位同学是否都讲对了一个。如果不是,再尝试下一种情况:洞庭最大,洪泽第二,鄱阳第四,太湖第三,再检查每位同学是否都讲对了一个。尝试所有可能的情况,直到满足每位同学都讲对一个为止。
slide45
枚举法—续
  • 为了尝试所有情况,我们需要假设洞庭湖可能是最大,也可能是第二、第三或第四。因此,a的值可能从1变到4。同样,b, c ,d的值也都可能从1变到4。为此,我们需要一个控制结构,使a, b, c, d的值能自动从1变到4。这种结构就是循环结构。
slide46
四大湖排列问题的解

问题:效率差

解决方法:一旦找到答案就应该结束

main()

{ int a, b, c, d;

for (a=1; a<=4; ++a)

for (b=1; b<=4; ++b)

if ( a == b) continue;

else for (c=1; c<=4; ++c)

if (c==a||c==b) continue;

else {d=10 – a – b - c;

if (((a==1)+(b==4)+(c==3))==1

&&((b==1)+(a==4)+(c==2)+(d==3))==1

&&((b==4)+(a==3))==1

&&((c==1)+(d==4)+(b==2)+(a==3))==1)

cout << a << b << c << d;

}

}

slide47

改进版1:

main()

{ int a, b, c, d; bool flag = false;

for (a=1; a<=4; ++a)

{ for (b=1; b<=4; ++b)

{ if ( a == b) continue;

else for (c=1; c<=4; ++c)

if (c==a||c==b) continue;

else {d=10 – a – b - c;

if (((a==1)+(b==4)+(c==3))==1 //注意

&&((b==1)+(a==4)+(c==2)+(d==3))==1

&&((b==4)+(a==3))==1

&&((c==1)+(d==4)+(b==2)+(a==3))==1)

{ cout << a << b << c << d;

flag = true; break; }

}

if (flag) break;}

if (flag) break;}

} //break 只能退出当前循环体

程序不够简练

slide48

改进版2

main()

{ int a, b, c, d; bool flag = false;

for (a=1; a<=4 && !flag; ++a)

{ for (b=1; b<=4 && !flag; ++b)

{ if ( a == b) continue;

else for (c=1; c<=4 ; ++c)

if (c==a||c==b) continue;

else {d=10 – a – b - c;

if (((a==1)+(b==4)+(c==3))==1

&&((b==1)+(a==4)+(c==2)+(d==3))==1

&&((b==4)+(a==3))==1

&&((c==1)+(d==4)+(b==2)+(a==3))==1)

{ cout << a << b << c << d;

flag = true; break; }

}

}

}

}

slide49
列出ABC三个字母的全排列
  • 解题思路:
    • 让第一个位置的值从A依次变到C
    • 让第一个位置的值从A依次变到C
    • 让第一个位置的值从A依次变到C
    • 注意三个位置的值不能相同
  • 可以用一个三层的嵌套循环实现,循环变量是字符类型
slide50
int main()

{ char c1, c2, c3;

for (c1 = ‘A’; c1 <= ‘C’; ++c1)

for (c2 = ‘A’; c2 <= ‘C’; ++c2)

if (c1 == c2) continue;

else for (c3 = ‘A’; c3 <= ‘C’; ++c3)

if ((c3 == c1 || c3 == c2))

continue;

else cout << c1 << c2 << c3 << endl;

}

slide51
贪婪法的基本思想
  • 在求解过程的每一步都选取一个局部最优的策略,把问题规模缩小,最后把每一步的结果合并起来形成一个全局解。
  • 基本步骤:
    • 从某个初始解出发
    • 采用迭代的过程,当可以向目标前进一步时,就根据局最优策略,得到一个部分解,缩小问题规模。
    • 将所有解综合起来
slide52
硬币找零问题
  • 对于一种货币,有面值为1分, 2分, 5分和1角的硬币,最少需要多少个硬币来找出K分钱的零钱。
slide53
贪婪法解题思想
  • 不断地使用面值最大的硬币。如要找零的值小于最大的硬币值,则尝试第二大的硬币。依此类推。
  • 不断尝试的过程就是循环
slide54

#include<iostream>

using namespace std;

#define ONEFEN 1

#define TWOFEN 2

#define FIVEFEN 5

#define ONEJIAO 10

int main()

{ int money;

int onefen = 0, twofen = 0, fivefen = 0, onejiao = 0;

cout << "输入要找零的钱(以分为单位):";

cin >> money;

slide55

//不断尝试每一种硬币

while (money >= ONEJIAO) {onejiao++; money -= ONEJIAO;}

while (money >= FIVEFEN) {fivefen++; money -= FIVEFEN;}

while (money >= TWOFEN) {twofen++; money -= TWOFEN;}

while (money >= ONEFEN) {onefen++; money -= ONEFEN;}

//输出结果

cout << "1角硬币数:" << onejiao << endl;

cout << "5分硬币数:" << fivefen << endl;

cout << "2分硬币数:" << twofen << endl;

cout << "1分硬币数:" << onefen << endl;

return 0;

}

slide56

例:用贪心法求解付款问题。

假设有面值为5元、2元、1元、5角、2角、1角的货币,需要找给顾客4元6角现金,为使付出的货币的数量最少,首先选出1张面值不超过4元6角的最大面值的货币,即2元,再选出1张面值不超过2元6角的最大面值的货币,即2元,再选出1张面值不超过6角的最大面值的货币,即5角,再选出1张面值不超过1角的最大面值的货币,即1角,总共付出4张货币。

slide57
在付款问题每一步的贪心选择中,在不超过应付款金额的条件下,只选择面值最大的货币,而不去考虑在后面看来这种选择是否合理,而且它还不会改变决定:一旦选出了一张货币,就永远选定。付款问题的贪心选择策略是尽可能使付出的货币最快地满足支付要求,其目的是使付出的货币张数最慢地增加,这正体现了贪心法的设计思想。
slide58
思考题
  • Nefu 90题今年暑假不AC
slide59
“今年暑假不AC?”“是的。”“那你干什么呢?”“看世界杯呀,笨蛋!”“@#$%^&*%...”确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)“今年暑假不AC?”“是的。”“那你干什么呢?”“看世界杯呀,笨蛋!”“@#$%^&*%...”确实如此,世界杯来了,球迷的节日也来了,估计很多ACMer也会抛开电脑,奔向电视了。作为球迷,一定想看尽量多的完整的比赛,当然,作为新时代的好青年,你一定还会看一些其它的节目,比如新闻联播(永远不要忘记关心国家大事)、非常6+7、超级女生,以及王小丫的《开心辞典》等等,假设你已经知道了所有你喜欢看的电视节目的转播时间表,你会合理安排吗?(目标是能看尽量多的完整节目)
slide60
Input
  • 输入数据包含多个测试实例,每个测试实例的第一行只有一个整数n(n<=100),表示你喜欢看的节目的总数,然后是n行数据,每行包括两个数据Ti_s,Ti_e (1<=i<=n),分别表示第i个节目的开始和结束时间,为了简化问题,每个时间都用一个正整数表示。n=0表示输入结束,不做处理。
  • Output
  • 对于每个测试实例,输出能完整看到的电视节目的个数,每个测试实例的输出占一行。
slide61
输入:
  • 1 2
  • 1 3
  • 3 4
  • 0 7
  • 3 8
  • 15 19
  • 15 20
  • 10 15
  • 8 18
  • 6 12

5 10

4 14

2 9

0

输出:

5

slide62
先按结束时间排下序(从小到大)
  • 1 3 0 3 2 5 6 4 10 8 15 15
  • 3 4 7 8 9 10 12 14 15 18 19 20
  • 竖着看!
  • 用心一算:
  • 1 3 5 10 15
  • 3 4 10 15 19
  • 本题可以冒泡
slide63

int main()

  • {
  • int tmp,n,s,e,l[5],w[5];
  • n=4;
  • for(int i=1;i<=4;i++ )
  • {cin>>l[i]; cin>>w[i];}
  • for(int i=1;i<n;i++) //这是对2个数组的冒泡,先排第1个位置,最小的
  • {tmp=i;
  • for(int j=i+1;j<=n;j++)
  • if (l[j]<l[tmp]) tmp=j;
  • s=l[i];l[i]=l[tmp];l[tmp]=s; //看好
  • e=w[i];w[i]=w[tmp];w[tmp]=e; //跟着拍了
  • }
  • for(int i=1;i<=4;i++ )
  • { cout<<l[i]<<" "<<w[i]<<endl;
  • }
  • return 0;
  • }
slide65
暑假不AC 的贪婪代码
  • #include <iostream>
  • using namespace std;
  • int main()
  • {
  • int n;
  • int inp_s[100],inp_e[100];//开始,结束 2个数组
  • int s_tmp,e_tmp;
  • while(cin>>n)
  • {
  • if (n==0) break;
  • for(int i=1;i<=n;i++)
  • cin>>inp_s[i]>>inp_e[i];
slide66

//排序

  • int tmp=0;
  • for(int i=1;i<=n-1;i++)
  • {
  • tmp=i;
  • for(int j=i+1;j<=n;j++)
  • if (inp_e[j]<inp_e[tmp]) tmp=j;
  • e_tmp=inp_e[i],inp_e[i]=inp_e[tmp],inp_e[tmp]=e_tmp;
  • s_tmp=inp_s[i],inp_s[i]=inp_s[tmp],inp_s[tmp]=s_tmp;
  • }
slide67
输出结果
  • int sum=0;
  • tmp=inp_e[1];
  • for(int i=2;i<=n;i++)
  • {
  • if (tmp<=inp_s[i]) {sum++; tmp=inp_e[i];}
  • }
  • cout<<sum+1<<endl;
  • }
  • //cout << "Hello world!" << endl;
  • return 0;
  • }