c语言百文百鸡问题答案,算法的举例(。。。

三、算法举例

(一)穷举算法

特点:对问题的所有可能状态一一测试,直到找到解或全部可能状态测试过为止。

典型问题:搬砖问题

百文百鸡问题

百马百担问题

一元钱组合问题

大量数据录入问题

1.某地需要搬运砖块,已知男人一人搬3块,女人一人搬2块,小孩两人搬一块。

问用45人正好搬45块砖,有多少种搬法?

for (men = 0; men <= 45; men++)

第一种方法:使用三重循环,将男人、女人、小孩的可能状态全部列举出来。

for (women = 0; women <= 45; women++)

for (child = 0; child <= 45; child++)

if ((men+women+child45) && (men3+women2+child*0.545))

printf(“men=%d women=%d child=%d\n”, men, women, child);

第二种方法:使用两重循环,将男人、女人的可能状态全部列举出来,小孩的状态由条件推导而出。

for (men = 0; men <= 15; men++)

for (women = 0; women <= 22; women++)

{

child = 45 – women – men;

if (men * 3 + women * 2 + child * 0.5 == 45)

printf(“men=%d women=%d child=%d\n”, men, women, child);

}

(二)迭代算法特点:不断用新值取代旧值(或旧值递推出新值)的过程。

典型问题: 银行利率计算问题

人口增长问题

兔子繁殖问题(Fibonacci数列)

一元方程的迭代解法

例如:1. 现有12亿人,每年递增2%,十年后将有多少人?

初值m=12

m=m*(1+2%) 第一年后人口

m=m*(1+2%) 第二年后人口

2. 一对新生兔子,从第三月开始它们每个月都生一对兔子,按此规律,假设没有兔子死亡,一年后共有多少兔子?

x1=1,x2=1; 第一个月 第二个月

x=x1+x2 x为当前月,x2为上月, x1为上上月

x1=x2; 新值取代旧值

x2=x; 新值取代旧值

程序代码:

#includeint main()

{

long x1,x2,x,i;

x1=1;x2=1;

for(i=1;i<=12;i++)

{

if(i<3) x=1;

else

{

x=x1+x2;

x2=x1;

x1=x;

}

printf(" %5d",x);

}

}

3.二分法解方程

一元多次方程 f(x)=x3-2x2-3=0;

在函数f(x)上任取两点,须保证f(x1)和f(x2)的值异号。

x=(x1+x2)/2;

若f(x)与f(x1)同号,则x1=x; 否则 x2=x;重复直到f(x)<= ε。

答案:x=2.485544

程序代码:

#include#define EP 1.0e-5

int main()

{

double x1,x2,x;

double f(double x);

printf(“Please input x1,x2:”);

scanf("%lf%lf",&x1,&x2);

do

{

x=(x1+x2)/2;

if(f(x1)*f(x)>0)

x1=x;

else x2=x;

}while(fabs(f(x))>EP);

printf(" x=%f\n",x);

}

double f(double x)

{

double y;

y=xxx-2xx-3;

return y;

}

牛顿迭代法解方程

一元多次方程 f(x)=x3-2x2-3=0;

切线方程y= f(xk)+f’(xk).(x-xk)

与x轴交点 f(xk)+f’(xk).(x-xk)=0

解为x (k+1)=xk-f(xk)/f’(xk);

重复直到f(x)<=ε

答案:x=2.485544

程序代码:

方程 f(x)=x3-2x2-3=0;

#include#define EP 1.0e-5

main()

{

double x;

double f(double x);

double f1(double x);

printf(“Please input x:”);

scanf("%lf",&x);

do

{

x=x-f(x)/f1(x);

}while(fabs(f(x))>EP);

printf(" x=%f\n",x);

}

double f(double x) /计算f(x)值的函数/

{

double y;

y=xxx-2xx-3;

return y;

double f1(double x) /计算f(x)导数值的函数/

{

double y;

y=3xx-4*x;

return y;

}

5.求两个正整数的最大公约数(辗转相除法)

两个正整数u和v

辗转相除 例

r=u%v r=10%4 r=4%2

u=v u=4; u=2;

v=r; v=2; v=0;

最后余数为0时,u的值即为两个数的最大公约数.

程序代码

#includemain()

{

int a,b,u,v,r;

printf(“Please input a,b:”);

scanf("%d%d",&a,&b);

u=a;v=b;

do

{

r=u%v;

u=v;

v=r;

}while(r!=0);

printf(" %d and %d gcd is %d\n",a,b,u);

}

6.输入一个正整数m,判断它是否为素数。素数:只能被1和自身整除的正整数,1不是素数,2是素数。

算法:除了1和m,不能被其它数整除。

设 i 取值 [2, m-1]

如果m不能被该区间上的任何一个数整除,即对每个i,m%i 都不为0,则m是素数

只要找到一个i,使m%i为0,则m肯定不是素数

m %2 %3 %4 %5 %(m-1)

不是素数 || =0 =0

是素数 && !=0 !=0

m不可能被大于 m/2 的数整除,故 i可取值 [2, m-1] 、 [2, m/2] 、 [2, sqrt(m)]

/* 判断正整数m是否为素数 /

#include int main(void)

{

int i, m;

printf("Enter a number: "); / 输入提示 /

scanf ("%d", &m);

for(i = 2; i <= m/2; i++) / 第9行 /

if(m % i == 0) break; / 若m能被某个i整除,则m不是素数,提前结束循环 /

if(i > m/2)/ 如果循环正常结束,说明m不能被任何一个i整除,则m是素数 /

printf("%d is a prime number! \n", m);

else

printf(“No!\n”); / 第15行 /

return 0;

}

8. 整数个位分解问题(从高位开始分解)

输入一个整数,从高位开始逐个数字输出,例如12345

Step 1: 12345 /10000 = 1

12345 %10000 =2345

Step 2: 2345 /1000 = 2

2345%1000 =345

Step 3: 345 /100 = 3

345%100 =45

Step 4: 45 /10 = 4

45%10 =5

Step 5: 5/1= 5

5%1=0

End

1) 如何得到10000

找输入数据对应的幂

pow=1; temp = x;

while (x != 0) {

pow = pow * 10;

x =x /10;

}

pow = pow /10;

(2) 每次循环pow缩小1/10

(3) 直到pow=0结束。

代码:

#include “stdio.h”

int main()

{

long x,pow,temp;

scanf("%ld",&x);

if(x<0)x=-x;

pow=1;temp=x;

while(x!=0)

{

pow=pow10;

x=x/10;

}

pow=pow/10;

x=temp;

while(pow!=0)

{

printf("%5d",x/pow);

x=x%pow;

pow=pow/10;

}

printf("\n");

return 0;

}

9. 整数个位分解问题(从个位开始分解)

输入一个整数,从个位开始逐个数字输出,例如12345

Step 1: 12345 %10 = 5

12345 /10 =1234

Step 2: 1234 % 10 = 4

1234/10 =123

Step 3: 123 % 10 = 3

123/10 =12

Step 4: 12 % 10 = 2

12 /10 =1

Step 5: 1% 10= 1

1/10=0

End /* 统计一个整数的位数 /

程序代码:

#include int main(void)

{

int count, number,m; / count 记录整数number的位数 /

count = 0;

printf(“Enter a number:”); / 输入提示 /

scanf ("%d", &number);

if(number < 0) number = -number; / 将输入的负数转换为正数 /

do{

m=number%10; / 整数求余得到个位数*/

number = number / 10; /* 整除后减少一位个位数,组成一个新数 /

count ++; / 位数加1 /

printf("%5d", m); / 输出个位*/

}while(number != 0); /* 判断循环条件 */

printf("\nIt contains %d digits.\n", count);

return 0;

}

10. 使用格里高利公式求π的近似值,要求精确到最后一项的绝对值小于10–4。

代码:

/* 用格里高利公式计算π的近似值,精度要求:最后一项的绝对值小于0.0001 /

#include #include / 程序中调用绝对值函数 fabs,需包含 math.h /

int main( )

{

int i, flag;

double item, pi; / pi 用于存放累加和 /

/ 循环初始化 /

flag = 1; / flag 表示第 i 项的符号,初始为正,每次循环改变符号*/

i = 1; /* 表示第 i 项的分母,初始为1 /

item = 1.0; / item 中存放第 i 项的值,初值取 1 /

pi = 0; / 置累加和 pi 的初值为0 */

/* 当|item| ≥ 0.0001时,执行循环 /

while(fabs(item) >= 0.0001)

{

item = flag * 1.0 /i; / 计算第 i 项的值 /

pi = pi + item; / 累加第 i 项的值 /

flag = -flag; / 改变符号,为下一次循环做准备 /

i= i + 2; / 分母递增2 ,为下一次循环做准备 /

}

pi = pi * 4; / 循环计算的结果是 pi/4 */

printf (“pi = %f\n”, pi);

return 0;

}

11.阶乘计算

/* 使用函数计算 1! + 2! + 3! + … + 100! /

#include double fact (int n); / 函数声明 /

int main(void)

{

int i;

double sum;

sum = 0;

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

sum = sum + fact (i); / 调用fact(i)求i!,共重复100次 /

printf(“1! + 2! + … + 100! = %e\n”, sum); / 用指数形式输出结果 */

return 0;

}

/* 定义求 n! 的函数 /

double fact (int n)

{

int i;

double result; / 变量 result 中存放阶乘的值 /

result = 1; / 置阶乘 result 的初值为1 /

for(i = 1; i <= n; i++) / 循环执行n次,计算n! /

result = result * i;

return result; / 把结果回送主函数 */

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值