从蛮力到策略—百鸡问题与完美立方

(1)百鸡问题

“鸡翁一,值钱五;鸡母一,值钱三;鸡雏三,值钱一。百钱买百鸡,问鸡翁、母、雏各几何?”

  • :在不甚思考的情况下(每种鸡都可能有0-100只)凭直觉写出蛮力法求解百鸡问题的基本思路并编程实现,思考该算法复杂度的渐进表达式。

设鸡翁为x,鸡母为y,鸡雏为z,根据问题要求我们就能有以下两个公式:

         5x+3y+1/3z=100

         x+y+z=100

然后我们就能根据这个数学模型来编写代码

  • :缩小三种鸡数量可能的范围,优化算法,减少计算量,此时算法复杂度是否减少?

缩小鸡的范围,我们可以通过简单的数学计算得到:鸡翁百钱最多买20只,鸡母最多买33只,鸡雏最多100只,这样我们就能给代码加上条件,提升运算速度。

  • :进一步优化算法,能否降低算法的复杂度?请写出思路并编程实现。

进一步思考,我们发现z(鸡雏)可以用x和y表示(这类问题最好把非整数转换成其他数表示),这样我们就能得到:z=100-x-y

代码粘贴区:

1.#include<iostream>
using namespace std;


int main(){
	int x,y,z;
	for(x=0;x<=100;x++)
		for(y=0;y<=100;y++)
			for(z=0;z<=100;z++)
				if((x+y+z==100)&&(5*x+3*y+z/3)==100&&z%3==0)
					cout<<"x="<<x<<" "<<"y="<<y<<" "<<"z="<<z<<endl;							      					
	return 0;
}

2.#include<iostream>
using namespace std;

//鸡翁为x,鸡母为y,鸡雏为z。 
int main(){
	int x,y,z;
	for(x=0;x<=20;x++)
		for(y=0;y<=33;y++)
			for(z=0;z<=100;z++)
				if((x+y+z==100)&&(5*x+3*y+z/3)==100&&z%3==0)
					cout<<"x="<<x<<" "<<"y="<<y<<" "<<"z="<<z<<endl;							      					
	return 0;
}

3.#include<iostream>
using namespace std;

//鸡翁为x,鸡母为y,鸡雏为z。 
int main(){
	int x,y,z;
	for(x=0;x<=20;x++)
		for(y=0;y<=33;y++){
			z=100-x-y; 
			if((5*x+3*y+z/3)==100&&z%3==0)
			cout<<"x="<<x<<" "<<"y="<<y<<" "<<"z="<<z<<endl;
		} 
			
											      					
	return 0;
}

运行结果截图:

  • :调整输入规模(如1000鸡1000钱问题、2000鸡2000钱问题等),观察并记录至少5组(每组多次运行取平均值)不同输入规模下任务1和任务3算法的运行时间,制作excel图表进行对比。

(2)掌握枚举算法的基本思想和实现方法。

任务描述: 如a3= b3 + c3 + d3的等式被称为完美立方等式。例如 123= 63 + 83 + 103 。编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得等式成立,其中a,b,c,d 大于 1, 小于等于N,且 b<=c<=d。

输入:一个正整数N (N≤100)。 l

输出:每行输出一个完美立方。输出格式为:a^3=b^3+c^3+d^3。 其中a,b,c,d所在位置分别用实际求出四元组值代入。

请按照a的值,从小到大依次输出。当两个完美立方等式中a值相同时,b值小的优先输出,若b仍相同,c值小的优先输出,c再相同时d值小的先输出。

样例输入

24

样例输出

6^3=3^3+4^3+5^3

12^3=6^3+8^3+10^3

18^3=2^3+12^3+16^3

18^3=9^3+12^3+15^3

19^3=3^3+10^3+18^3

20^3=7^3+14^3+17^3

24^3=12^3+16^3+20^3

代码粘贴区:

#include<iostream>
using namespace std;

int main(){
	int a,b,c,d;
	int N;
	cout<<"输入N";
	cin>>N;
	for(a=2;a<=N;a++){
		for(b=2;b<=a;b++)
			for(c=b;c<=a;c++)
				for(d=c;d<=a;d++){
					if(a*a*a==b*b*b+c*c*c+d*d*d)
					cout<<a<<"^3="<<b<<"^3+"<<c<<"^3+"<<d<<"^3"<<endl;
			}
			
		
	}
	return 0;
}

运行结果截图:

3)理解完美立方问题和求年龄问题的求解思路。

任务描述:年龄几何:张三、李四、王五、刘六的年龄成一等差数列,他们四人的年龄相加是26,相乘是 880,求以他们的年龄为前4项的等差数列的前20项。

先读题,抽象出数学模型,根据数学模型写代码,然后优化代码。

int main(){

int a,x;

for(a=1;a>=1&&a<=6;a++){

for(x=1;x>=1&&x<=4;x++){

if(4*a+6*x==26&&a*(a+x)*(a+x+x)*(a+x+x+x)==880){

for (int i = 1; i < 20; i++,a=a+x) {

     cout << a << " ";

}

}

}

}

return 0;

}

实验总结

  1. 为什么不使用时间单位来表示时间复杂度。

因为这是没有办法比较的,比如算法A的相对时间是T(n)= 100n,算法B的相对时间是T(n)= 5n^2,这两个到底谁的运行时间更长一些?这就要看n的取值了。所以才会有时间复杂度这个概念。

(2)谈谈你对不同量级时间复杂度的直观认识。

T(n) =  O(n)在函数表示是直线,T(n) =  O(logn)趋近某一个数的曲线,上凸。T(n) =  O(n^2)变化越来越快的函数。O(logn)< O(n)< O(n^2)

  1. 编程提示

如何记录一段代码的执行时间:

C语言: #include <time.h> int start=clock();int end=clock();int t=end-start;

JAVA:long startTime=System.currentTimeMillis();

long endTime=System.currentTimeMillis();

long Time=endTime-startTime;

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值