算法分析中的几个经典例子

算法分析中的几个经典例子
算法分析中的几个经典例子

*分析过程:

由于主管道是东西走向,那么通过主轴线的y坐标可唯一确定其位置。由带权中位数问题可知,其中位数即为管道最优解。

用一个线性时间选择找中位数算法,即可在O(n)时间内解此问题。

这里采用RandomizedSelect算法。

油井数可能为奇数或者偶数

奇数则取其中位数

偶数则取两个中位数中的任意一个

*/

#include

#include

#include

#define LEN 100

using namespace std;

int Random(int p, int r){//随机化

return rand()*(r-p)/32767+p;

}

void Swap(int &a, int &b){

int temp = a;

a = b;

b = temp;

}

int Partition(int y[LEN], int p, int r){

int i = p, j = r+1;

int x = y[p];

while(true){

while(y[++i]

while(y[--j]>x);

if(i>=j) break;

Swap(y[i],y[j]);

}

y[p] = y[j];

y[j] = x;

return j;

}

int RandomizedPartition(int y[LEN], int p, int r){

int i = Random(p,r);

Swap(y[i],y[p]);

return Partition(y,p,r);

}

int RandomizedSelect(int y[LEN], int p, int r, int k){

if(p==r) return y[p];

int i = RandomizedPartition(y,p,r);

int j = i-p+1;

if(k<=j) return RandomizedSelect(y,p,i,k);

else return RandomizedSelect(y,i+1,r,k-j);

}

void main(){

int n;//油井数

int sum = 0;//管道长度总和

int y[LEN];//油井y坐标

int dy;//油井y坐标中位数

freopen("input.txt","r",stdin);//打开一个输入流,读取input.txt文件

freopen("output.txt","w",stdout);//打开一个输出流,写output.txt文件

scanf("%d",&n);//读取油井数

for(int i=0;i

scanf("%d",&y[i]);//x坐标在此题中无用,而y坐标在x坐标之后写入。因此两次写入一样的数组y[LEN]

scanf("%d",&y[i]);

}

dy = RandomizedSelect(y, 0, n-1, (n+1)/2);//中位数求取

for(i=0; i

sum+=abs(y[i]-dy);//计算管道和

printf("%d\n",sum);

fclose(stdin);//关闭输入流

fclose(stdout);//关闭输出流

}

邮局选址的分治算法,C++语言

2008-11-25 13:28

提问者:哆啦没做梦|悬赏分:200 |浏览次数:1080次

一道我们算法课上留的作业题,大概内容是:某市有n个小区(坐标给出),每个小区的住户数不相同(带权)。现有一邮局将建在某小区内,要求到各个用户的距离之和最短,用分治法解答。

请高手帮下忙,很急,在线等。请注解详细点,采用后积分倾囊相赠!

问题补充:

必须用分治法的,因为是分治法那章留的题。

分治是在小区坐标的地方,把横纵坐标分开来计算,好像是利用中位点求解的。拜托了!

2008-11-25 14:43

最佳答案

代码如下:

#include

#include

#include

#include

using namespace std;

const int MAXN = 10000;

typedef struct {int idx, l;} Rst;

int n, x[MAXN], y[MAXN], num[MAXN];

Rst f(int s, int e)

//分治求解, 参数s,e为小区编号, 函数求出从s到e编号的小区中, 哪一个到所有小区的加权距离和最短, 并返回距离和与小区编号

{

int i;

if (s == e) //如果区间里面只有一个小区, 显然返回该小区

{

Rst rst = {s, 0};

for (i=0; i

(y[s]-y[i])*(y[s]-y[i]));

return rst;

}

else //否则, 分别找出左半和右半区间中的最佳小区, 谁更优, 就返回谁

{

Rst a = f(s, (s+e)/2), b = f((s+e+1)/2, e);

return a.l

}

}

int main()

{

int i, j, k;

cout << "请输入小区数量:";

cin>>n;

cout<<"请分别输入"<

for (i=0; i

{

cout<<"第"<

cin>>x[i]>>y[i]>>num[i];

}

Rst rst = f(0, n-1); //0到n-1为所有小区编号, 则返回值就是最终结果

cout<<"到各个用户的距离之和最短的小区编号: "<

return 0;

}

//最后说两句, 算法时间复杂度O(n^2), 其实就跟枚举没有区别..

//这个题目布置的不好根本体现不出分治算法的优势

4

向TA求助

回答者:deitytoday|五级

擅长领域:C/C++程序设计

参加的活动:暂时没有参加的活动

提问者对于答案的评价:

非常感谢,主函数有一点小问题,刚刚改了下已经能运行了。

分给你了!

相关内容

?2008-10-7大家帮帮忙,用递归算法的分治策略求一个数组的众数,用c语言编写,告诉 (1)

?2007-9-19邮局把信件自动分检使用的是哪种计算机技术? A机器翻译B 自然语言理解C (3)

?2009-6-10学校超市选址,c语言采用数据结构编写 1

?2009-5-31C语言数据结构超市选址

?2011-5-21求用FLOYD算法解此矩阵,并附带floyd的c语言程序,矩阵中M_A_X表两点不 (2)

更多关于邮局选址问题代码?的问题>>

查看同主题问题:算法 c++c++ 语言邮局选址

等待您来回答

?0回答大三的线性代数课件

?2回答请问谁有建筑结构基础与识图,中国建筑工业出版社的第二版的课件ppt,...

?0回答高一英语必修一unit3 Discovering useful structures 3 (人教版)

?0回答人教版六年级数学目标检测第三单元检测

?2回答我昨天才发现我老公我婚外情的,我只找到他最近特别爱找茬,昨天无意...

?0回答100高分跪求2011年11月的证券从业资格考试基础知识,证券交易,基金,投...

?1回答那里有优秀的ppt化学课件呢

?1回答人教版高一地理必修一1

更多等待您来回答的问题>>

其他回答共2条

2008-11-25 13:37 rupxup|三级

为什么用分支法呢?别的行不行?

2008-11-25 14:55 高金山|十四级

邮局选址问题

问题描述:

在一个按照东西和南北方向划分成规整街区的城市里,n个居民点散乱地分布在不同的街区中。用x坐标表示东西向,用y坐标表示南北向。各居民点的位置可以由坐标(x,y)表示。街区中任意2点(x1,y1)和(x2,y2)之间的距离可以用数值

|x1-x2|+|y1-y2|度量。

居民们希望在城市中选择建立邮局的最佳位置,使n个居民点到邮局的距离总和最小。

编程任务:

给定n个居民点的位置,编程计算n个居民点到邮局的距离总和的最小值。

数据输入:

由文件input.txt提供输入数据。文件的第1行是居民点数n,1≤n≤10000。接下来n行是居民点的位置,每行2个整数x和y,-10000≤x,y≤10000。

结果输出:

程序运行结束时,将计算结果输出到文件output.txt中。文件的第1行中的数是n个居民点到邮局的距离总和的最小值。

输入文件示例

5

1 2

2 2

1 3

3 -2

3 3

输出文件示例

10

解法:

https://www.360docs.net/doc/ac12333993.html,/lyflower/archive/2008/03/07/2156943.aspx

//- By CQ.Xiao @ SCAU

//- Nov.9th 2007

#include "iostream"

using namespace std;

struct info{

unsigned dis; //最小值

unsigned r; //标号r之前(包括r)的村庄为一个辖区

};

//-- Definition for Global-Variable

unsigned village = 0, postoffice = 0; //number of village & postoffice unsigned *xCoordinate = NULL; //x coordinate of each village

unsigned **center = NULL, **dis = NULL; //point for Center(l,r) & Dis(l,r)

info **totalDis = NULL; //point for TotalDis(t,k)

//-- Function Declare

void input();

void calculateCenter();

void calculateDis();

void calculateTotalDis();

void output(unsigned t, unsigned k);

void setFree();

int main(){

input();

calculateCenter();

calculateDis();

calculateTotalDis();

output(0, postoffice);

setFree();

return 0;

}

void input(){

//--- Input

cin >> village >> postoffice;

xCoordinate = new unsigned [village];

for (unsigned i = 0; i < village; i++)

cin >> xCoordinate[i];

//--- Sort

int t = 0;

for (i = 0; i < village - 1; i++)

for (int j = 0; j < village - 1 - i; j++)

if (xCoordinate[j] > xCoordinate[j+1]){

t = xCoordinate[j];

xCoordinate[j] = xCoordinate[j+1];

xCoordinate[j+1] = t;

}

}

void calculateCenter(){

//--- 内存分配

center = new unsigned *[village]; //动态分配二维数组的第一维for (unsigned i=0; i

//--- 初始化Center(l,r)

for (unsigned l = 0; l < village; l++)

for (unsigned r = l; r < village; r++)

center[l][r] = xCoordinate[(r-l)/2 + l];

}

void calculateDis(){

//--- 内存分配

dis = new unsigned *[village]; //动态分配二维数组的第一维

for (unsigned i = 0; i < village; i++) //动态分配二维数组的第二维

dis[i] = new unsigned[village];

//--- 初始化Dis(l,r)

for (unsigned l = 0; l < village; l++)

for (unsigned r = l; r < village; r++){

dis[l][r] = 0;

for (unsigned k = l; k <= r; k++)

if (center[l][r] > xCoordinate[k])

dis[l][r] += center[l][r] - xCoordinate[k]; //计算unsigned时不要得出负数else

dis[l][r] += xCoordinate[k]- center[l][r];

}

}

void calculateTotalDis(){

//--- 内存分配

totalDis = new info *[village]; //动态分配二维数组的第一维

for (unsigned i = 0; i < village; i++) //动态分配二维数组的第二维

totalDis[i] = new info[postoffice+1];

//--- 计算TotalDis(v,p+1)

//---- 当k=1时,根据公式(1.2),直接计算

for (unsigned t = 0; t < village; t++)

totalDis[t][1].dis = dis[t][village-1];

//---- 当k=2,3,...,p时的情况

for (unsigned k = 2; k <= postoffice; k++)

for (unsigned t = 0; t < village; t++){

totalDis[t][k].dis = (unsigned)(-1);

totalDis[t][k].r = 0;

for (unsigned r = t; r <= village-k; r++){

unsigned temp = dis[t][r] + totalDis[r+1][k-1].dis;

//---- 计算最小值

if (temp < totalDis[t][k].dis){

totalDis[t][k].dis = temp;

totalDis[t][k].r = r;

}

}

}

}

void output(unsigned t, unsigned k){

if (1 == k)

cout << center[t][village-1];

else{

cout << center[t][totalDis[t][k].r] << ' '; output(totalDis[t][k].r+1, k-1);

}

}

void setFree(){

//--释放动态分配的内存

for (unsigned i = 0; i < village; i++){ delete []center[i];

delete []dis[i];

delete []totalDis[i];

}

delete []center;

delete []dis;

delete []totalDis;

}

c语言经典算法

C语言的学习要从基础,100个经典的算法 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? ________________________________________________________________ 程序分析:兔子的规律为数列1,1,2,3,5,8,13,21.... __________________________________________________________________ 程序源代码: main() { long f1,f2; int i; f1=f2=1; for(i=1;i<=20;i++) { printf("%12ld %12ld",f1,f2); if(i%2==0) printf("\n");/*控制输出,每行四个*/ f1=f1+f2;/*前两个月加起来赋值给第三个月*/ f2=f1+f2;/*前两个月加起来赋值给第三个月*/ } } 上题还可用一维数组处理,you try! 题目:判断101-200之间有多少个素数,并输出所有素数。 _________________________________________________________________ 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。 ___________________________________________________________________ 程序源代码: #include "math.h" main() { int m,i,k,h=0,leap=1; printf("\n"); for(m=101;m<=200;m++) { k=sqrt(m+1); for(i=2;i<=k;i++) if(m%i==0) {leap=0;break;} if(leap) {printf("%-4d",m);h++; if(h%10==0) printf("\n"); } leap=1; } printf("\nThe total is %d",h); } 题目:打印出所有的“水仙花数”,所谓“水仙花数”是指一个三位数,其各位数字立方和等于该数本身。例如:153是一个“水仙花数”,因为153=1的三次方+5的三次方+3的三次方。 __________________________________________________________________ 程序分析:利用for循环控制100-999个数,每个数分解出个位,十位,百位。 ___________________________________________________________________ 程序源代码:

发散思维案例

发散思维案例 案例1 有一个古老的智力题:“树上有10只鸟,打死1只,还有几只?”最笨的回答是:“打死1只,还有9只。”最聪明的,也是被认为 唯一正确的答案是:“打死1只,就一只也没有了,因为它们都被 吓跑了。”在一次教学实践中,我还听到学生们说出了下面一些答案: 1、还有1只死鸟挂在树上; 2、还有9只,因为是用无声手枪击中的; 3、还有2只,树上鸟窝里有2只不会飞的雏鸟; 4、还有9只,在风雨交加的天气,枪声被掩盖了; 5、还有1只,这只鸟是聋子; 6、还有10只,因为它们受伤飞不起来了; 案例2 有一只猪四百斤,一座桥承重两百斤,猪怎么过桥?条件: 1.猪是活猪,任何解决方案都不得切割猪 2.故事发生在猪王国,不要引入人的因素 3.是过桥,不是过河,不要说是游泳过去 4.是过桥,不是过涧,不要说是飞过去丫 5.桥是承重两百斤的桥,把桥挪到平地上抑或过另一座承重超过四百斤的桥都属改变性状 6.不是文字游戏,不要说“猪晕过去了” 1、立体思维

思考问题时跳出点、线、面的限制,立体式进行思维。 立体绿化:屋顶花园增加绿化面积、减少占地改善环境、净化空气。 立体农业、间作:如玉米地种绿豆、高粱地里种花生等 立体森林:高大乔木下种灌木、灌木下种草,草下种食用菌。 立体渔业:网箱养鱼充分利用水面、水体 立体开发资源:煤、石头、开发产品 你还能想出什么样的立体思维形式? 2、平面思维 以构思二维平面图形为特点的发散思维形式如用一支笔一张纸一笔画出圆心和圆周。 这种不连续的图形是难以一笔画出的 发散思维 3、逆向思维 背逆通常的思考方法。从相反方向思考问题的方法,也叫做反向思维。因为客观世界上许多事物之间甲能产生乙,乙也能产生甲。如:化学能能产生电能据此意大利科学家伏特1800年发明了伏打电池。反过来电能也能产生化学能,通过电解,英国化学家戴维1807年发现了钾、钠、钙、镁、锶、钡、硼等七种元素。 如说话声音高低能引起金属片相应的振动,相反金属片的振动也可以引起声音高低的变化。爱迪生在对电话的改进中,发明制造了世界上第一台留声机。 那么如何进行逆向思维呢? 1)就事物依存的条件逆向思考,如小孩掉进水里,把人从水中救起,是使人脱离水,司马光救人是打破缸,使水脱离人,这就是逆向思维。

贪心算法经典例题

贪心算法经典例题 发布日期:2009-1-8 浏览次数:1180 本资料需要注册并登录后才能下载! ·用户名密码验证码找回密码·您还未注册?请注册 您的账户余额为元,余额已不足,请充值。 您的账户余额为元。此购买将从您的账户中扣除费用0.0元。 内容介绍>> 贪心算法经典例题 在求最优解问题的过程中,依据某种贪心标准,从问题的初始状态出发,直接去求每一步的最优解,通过若干次的贪心选择,最终得出整个问题的最优解,这种求解方法就是贪心算法。 从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。 我们看看下面的例子 例1 均分纸牌(NOIP2002tg) [问题描述] 有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如 N=4,4 堆纸牌数分别为: ①9 ②8 ③17 ④ 6 移动3次可达到目的: 从③取 4 张牌放到④(9 8 13 10) -> 从③取 3 张牌放到②(9 11 10 10)-> 从②取 1 张牌放到①(10 10 10 10)。 [输入]:键盘输入文件名。 文件格式:N(N 堆纸牌,1 <= N <= 100) A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000) [输出]:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。 [输入输出样例] a.in: 4 9 8 17 6 屏慕显示:3 算法分析:设a[i]为第i堆纸牌的张数(0<=i<=n),v为均分后每堆纸牌的张数,s为最小移到次数。 我们用贪心法,按照从左到右的顺序移动纸牌。如第i堆(0

回溯法与分支限界法的分析与比较

回溯法与分支限界法的分析与比较 摘要:通过对回溯法与分支限界法的简要介绍,进一步分析和比较这两种算法在求解问题时的差异,并通过具体的应用来说明两种算法的应用场景及侧重点。 关键词:回溯法分支限界法n后问题布线问题 1、引言 1.1回溯法 回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。这种以深度优先方式系统搜索问题解的算法称为回溯法。 1.2分支限界法 分支限界法是以广度优先或以最小耗费优先的方式搜索解空间树,在每一个活结点处,计算一个函数值,并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解,这种方法称为分支限界法。 2、回溯法的基本思想 用回溯法解问题时,应明确定义问题的解空间。问题的解空间至少应包含问题的一个解。之后还应将解空间很好的组织起来,使得能用回溯法方便的搜索整个解空间。在组织解空间时常用到两种典型的解空间树,即子集树和排列树。确定了解空间的组织结构后,回溯法从开始结点出发,以深度优先方式搜索整个解空间。这个开始结点成为活结点,同时也成为当前的扩展结点。在当前的扩展结点处,搜索向纵深方向移至一个新结点。这个新结点就成为新的活结点,并成为当前扩展结点。如果在当前的扩展结点处不能再向纵深方向移动,则当前扩展结点就成为死结点。此时,应往回移动至最近的一个活结点处,并使这个活结点成为当前的扩展结点。回溯法以这种工作方式递归的在解空间中搜索,直至找到所要求的解或解空间中已无活结点时为止。 3、分支限界法的基本思想 用分支限界法解问题时,同样也应明确定义问题的解空间。之后还应将解空间很好的组织起来。分支限界法也有两种组织解空间的方法,即队列式分支限界法和优先队列式分支限界法。两者的区别在于:队列式分支限界法按照队列先进先出的原则选取下一个节点为扩展节点,而优先队列式分支限界法按照优先队列

C语言经典算法100例题目

看懂一个程序,分三步:1、流程;2、每个语句的功能;3、试数; 小程序:1、尝试编程去解决他;2、看答案;3、修改程序,不同的输出结果; 4、照答案去敲; 5、调试错误; 6、不看答案,自己把答案敲出来; 7、实在不会就背会。。。。。周而复始,反复的敲。。。。。 【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? ============================================================== 【程序2】 题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高 于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提 成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于 40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于 100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数? ============================================================== 【程序3】 题目:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?============================================================== 【程序4】 题目:输入某年某月某日,判断这一天是这一年的第几天? ============================================================== 【程序5】 题目:输入三个整数x,y,z,请把这三个数由小到大输出。 ============================================================== 【程序6】 题目:用*号输出字母C的图案。 ============================================================== 【程序7】 题目:输出特殊图案,请在c环境中运行,看一看,Very Beautiful! ============================================================== 【程序8】 题目:输出9*9口诀。 ============================================================== 【程序9】 题目:要求输出国际象棋棋盘。 ============================================================== 【程序10】 题目:打印楼梯,同时在楼梯上方打印两个笑脸。 -------------------------------------------------------------------------------- 【程序11】 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月 后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? ==============================================================

发散思维

发散思维 平阴县第二中学张树峰第八周 目标: 让学生了解发散思维的概念、特征及其应用,学会有效运用发散思维思考问题、分析问题、解决问题,培养发散思维能力。 重点:学会有效运用发散思维思考问题、分析问题、解决问题。 难点:运用发散思维解决实际问题。 教学过程 第一课时 一、导入 1、师:同学们一定都听过龟兔赛跑的故事,故事中兔子为什么失败? 因为它在途中睡了一觉。 2、师:假如故事中没写明原因,让你来猜,你会想到什么原因? …… 3、展示课本中“龟兔赛跑、兔子为什么落后”的发散思维图: 根据图示,引出发散思维概念。 二、了解发散思维的概念 1、Ppt打出发散思维的概念:发散思维又称辐射思维、放射思维、扩散思维或求异思维,是指大脑在思维时呈现的一种扩散状态的思维模式。 图示:

2、通过对“铅笔的用途”进行发散思维,加深对概念的理解: (1)让学生不看书,在P23页横线上写出铅笔除书写、画画以外的用途; (2)看书上例举的铅笔的用途。 小结:这就是典型的发散思维解决问题的方法,这种方法可以做到一题多解、一事多写、一物多用。有不少心理学家认为,发散思维是创造性思维的一个最主要的特点,是测定一个人或一个团队的创造力的主要指标之一。所以学会这种思维方法对任何一个人都非常重要。 三、发散思维的特征 Ppt显示发散思维的三个特征:流畅性、变通性和独特性。 下面通过一些例子帮助学生理解发散思维的三个特征: (一)流畅性 1、Ppt显示什么是流畅性: 流畅性指在尽可能短的时间内生成尽可能多的思维火花,产生心可能多的方式和方法,表达出尽可能多的思想和观念。 2、让学生看书上的例子:如果你有了钱可以干什么? 儿童A答:买可乐、买玩具车;

算法习题

算法设计与分析试卷 一、填空题(20分,每空2分) 1、算法的性质包括输入、输出、确定性、有限性。 2、动态规划算法的基本思想就将待求问题分解成若干个子问题、先求解子问题,然后 从这些子问题的解得到原问题的解。 3、设计动态规划算法的4个步骤: (1)找出最优解的性质,并刻画其结构特征。 (2)递归地定义最优值。 (3)以自底向上的方式计算出最优值。 (4)根据计算最优值得到的信息,构造最优解。 4、流水作业调度问题的johnson算法: (1)令N1={i|ai=bj}; (2)将N1中作业依ai的ai的非减序排序;将N2中作业依bi的非增序排序。 5、对于流水作业高度问题,必存在一个最优调度π,使得作业π(i)和π(i+1)满足Johnson不等式min{bπ(i),aπ(i+1)}≥min{bπ(i+1),aπ(i)}。 6、最优二叉搜索树即是最小平均查找长度的二叉搜索树。 二、综合题(50分) 1、当(a1,a2,a3,a4,a5,a6)=(-2,11,-4,13,-5,-2)时,最大子段和为∑ak(2<=k<=4)=20(5分) 2、由流水作业调度问题的最优子结构性质可知,T(N,0)=min{ai+T(N-{i},bi)}(1=sum){ sum=thissum; besti=i; bestj=j;} } return sum; } 4、设计最优二叉搜索树问题的动态规划算法OptimalBinarysearchTree? (15分) Void OptimalBinarysearchTree(int a,int n,int * * m, int * * w) { for(int i=0;i<=n;i++) {w[i+1][i]=a[i]; m[i+1][i]= 0;} for(int r=0;r

算法分析与程序设计动态规划及回溯法解背包问题

动态规划法、回溯法解0-1背包问题 2012级计科庞佳奇 一、问题描述与分析 1.动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会 有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。 不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。 多阶段决策问题中,各个阶段采取的决策,一般来说是与时间有关的,决策依赖于当前状态,又随即引起状态的转移,一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义,称这种解决多阶段决策最优化问题的方法为动态规划方法。任何思想方法都有一定的局限性,超出了特定条件,它就失去了作用。同样,动态规划也并不是万能的。适用动态规划的问题必须满足最优化原理和无后效性。1.最优化原理(最优子结构性质)最优化原理可这样阐述:一个最优化策略具有这样的性质,不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。简而言之,一个最优化策略的子策略总是最优的。一个问题满足最优化原理又称其具有最优子结构性质。2.无后效性将各阶段按照一定的次序排列好之后,对于某个给定的阶段状态,它以前各阶段的状态无法直接影响它未来的决策,而只能通过当前的这个状态。换句话说,每个状态都是过去历史的一个完整总结。这就是无后向性,又称为无后效性。3.子问题的重叠性动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。 01背包是在M件物品取出若干件放在空间为W的背包里,每件物品的体积为W1,W2……Wn,与之相对应的价值为P1,P2……Pn。求出获得最大价值的方案。 2.回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目 标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。 在包含问题的所有解的解空间树中,按照深度优先搜索的策略,从根结点出发深度探索解空间树。当探索到某一结点时,要先判断该结点是否包含问题的解,如果包含,就从该结点出发继续探索下去,如果该结点不包含问题的解,则逐层向其祖先结点回溯。(其实回溯法就是对隐式图的深度优先搜索算法)。若用回溯法求问题的所有解时,要回溯到根,且根结点的所有可行的子树都要已被搜索遍才结束。

C语言经典算法100例(1---30)

2008-02-18 18:48 【程序1】 题目:有1、2、3、4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 1.程序分析:可填在百位、十位、个位的数字都是1、2、3、4。组成所有的排列后再去 掉不满足条件的排列。 2.程序源代码: main() { int i,j,k; printf("\n"); for(i=1;i<5;i++) /*以下为三重循环*/ for(j=1;j<5;j++) for (k=1;k<5;k++) { if (i!=k&&i!=j&&j!=k) /*确保i、j、k三位互不相同*/ printf("%d,%d,%d\n",i,j,k); } } ============================================================== 【程序2】 题目:企业发放的奖金根据利润提成。利润(I)低于或等于10万元时,奖金可提10%;利润高 于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可可提 成7.5%;20万到40万之间时,高于20万元的部分,可提成5%;40万到60万之间时高于 40万元的部分,可提成3%;60万到100万之间时,高于60万元的部分,可提成1.5%,高于 100万元时,超过100万元的部分按1%提成,从键盘输入当月利润I,求应发放奖金总数? 1.程序分析:请利用数轴来分界,定位。注意定义时需把奖金定义成长整型。 2.程序源代码: main() { long int i; int bonus1,bonus2,bonus4,bonus6,bonus10,bonus; scanf("%ld",&i); bonus1=100000*0.1;bonus2=bonus1+100000*0.75; bonus4=bonus2+200000*0.5; bonus6=bonus4+200000*0.3; bonus10=bonus6+400000*0.15; if(i<=100000)

发散思维的例子

发散思维的例子 发散思维的例子一: 心理学家曾做过这样的试验:在黑板上画一个圆圈,问在座学生这是什么?其中大学生回答很一致:“这是一个圆。”而幼儿园的小朋友则给出了各种各样的答案:“太陽”、“皮球”、“镜子”……可谓五花八门。或许大学生的答案更加符合所画的图形,但是比起幼儿园孩子来说他们的答案是不是显得有些单调呆板呢? 发散思维的例子二: 1987年,我国在广西省南宁市召开了我国“创造学会”第一次学术研讨会。这次会议集中了全国许多在科学、技术、艺术等方面众多的杰出人才。为扩大与会者的创造视野,也聘请了国外某些著名的专家、学者。 其中有日本的村上幸雄先生。在会议中请村上幸雄先生为与会者讲学。他讲了三个半天,讲的很新奇,很有魅力,也深受大家的欢迎。其间,村上幸雄先生拿出一把曲别针,请大家动动脑筋,打破框框,想想曲别针都有什么用途?比一比看谁的发散性思维好。会议上一片哗然,七嘴八舌,议论纷纷。有的说可以别胸卡、挂日历、别文件,有的说可以挂窗帘、钉书本,大约说出了二十余种,大家问村上幸雄,“你能说出多少种”?村上幸雄轻轻地伸出三个指头。 有人问:“是三十种吗”?他摇摇头,“是三百种吗?”他仍然摇头,他说:“是三千种”,大家都异常惊讶,心里说:“这日本人果真聪明”。

然而就在此时,坐在台下的一位先生,他是中国魔球理论的创始人、著名的许国泰先生心里一阵紧缩,他想,我们中华民族在历史上就是以高智力著称世界的民族,我们的发散性思维绝不会比日本人差。于是他给村上幸雄写了个条子说:“幸雄先生,对于曲别针的用途我可 以说出三千种、三万种”。幸雄十分震惊,大家也都不十分相信。 许先生说:“幸雄所说曲别针的用途我可以简单地用四个字加以概括,即钩、挂、别、联。我认为远远不止这些。接着他把曲别针分解为铁质、重量、长度、截面、弹性、韧性、硬度、银白色等十个要素,用一条直线连起来形成信息的栏轴,然后把要动用的曲别针的各种要素用直线连成信息标的竖轴。再把两条轴相交垂直延伸,形成一个信息反应场,将两条轴上的信息依次“相乘”,达到信息交合……” 于是曲别针的用途就无穷无尽了。例如可加硫酸可制氢气,可加工 成弹簧、做成外文字母、做成数学符号进行四则运算等等,为中国人民在大会上创出了奇迹,使许多外国人十分惊讶!故事告诉我们发散性思维对于一个人的智力、创造力多么重要。 发散思维的例子三:一片叶子 一、在孩子、男人、女人、老人看来会有不同的认识,而在不同的 孩子、不同的老人看来又会不同,在不同的职业看来也会不同,还有不同的阶层、不同的地域…… 一片叶子,是绿色、是椭圆、是希望、是好心情…… 画家看来是一幅美丽的画

贪心算法概论

贪心算法概论 贪心算法一般来说是解决“最优问题”,具有编程简单、运行效率高、空间 复杂度低等特点。是信息学竞赛中的一个有为武器,受到广大同学们的青睐。本 讲就贪心算法的特点作些概念上的总结。 一、贪心算法与简单枚举和动态规划的运行方式比较 贪心算法一般是求“最优解”这类问题的。最优解问题可描述为:有n个输入,它的解是由这n 个输入的某个子集组成,并且这个子集必须满足事先给定的条 件。这个条件称为约束条件。而把满足约束条件的子集称为该问题的可行解。这 些可行解可能有多个。为了衡量可行解的优劣,事先给了一个关于可行解的函数,称为目标函数。目标函数最大(或最小)的可行解,称为最优解。 a)求“最优解”最原始的方法为搜索枚举方案法(一般为回溯法)。 除了极简单的问题,一般用深度优先搜索或宽度优先搜索。通常优化方法为利用约束条件进行可行性判断剪枝;或利用目标函数下界(或上界),根据当前最 优解进行分枝定界。 b)其次现今竞赛中用的比较普遍的动态规划(需要满足阶段无后效性原则)。 动态规划主要是利用最最优子问题的确定性,从后向前(即从小规模向大规模)得到当前最优策略,从而避免了重复的搜索。 举例说明:求多段图的最短路径。

在图(1)中,我们省略了各线段的长度。 如果用回溯法,搜索树大致如下: 显然,上面的搜索有大量重复性工作。比如节点8、9、10到11的最短路分别被调用了9次,从节点5、6、7到节点11也分别搜索了3次。 如果先算出节点8、9、10到11的最短路,由于它与前面的点无关,因此最优值确定下来,再用它们求定节点5、6、7 到节点11 的最短路径。同理,再用节 点5、6、7 的最优值,来求节点2、3、4 优值。最后从节点2、3、4 推出1 到 11的最优值。显然复杂度大为降低。 当然,如果本题把简单搜索改为搜索+记忆化的方法,则就是得能动态规划的原理,本质上就是动态规划,只是实现的方法不同与传统的表格操作法。搜索+记忆化算法有其特有的特点,以后再讨论。 c)贪心算法则不同,它不是建立在枚举方案的基础上的。它从前向后,根据当前情况,“贪心地”决定出下一步,从而一步一步直接走下去,最终得到解。 假如上面的例子中,我们定下这样的贪心策略:节点号k%3= =1。则有图3:

算法设计与分析:回溯法-实验报告

应用数学学院信息安全专业班学号姓名 实验题目回溯算法 实验评分表

实验报告 一、实验目的与要求 1、理解回溯算法的基本思想; 2、掌握回溯算法求解问题的基本步骤; 3、了解回溯算法效率的分析方法。 二、实验内容 【实验内容】 最小重量机器设计问题:设某一个机器有n个部件组成,每个部件都可以m个不同供应商处购买,假设已知表示从j个供应商购买第i个部件的重量,表示从j个供应商购买第i个部件的价格,试用回溯法求出一个或多个总价格不超过c且重量最小的机器部件购买方案。 【回溯法解题步骤】 1、确定该问题的解向量及解空间树; 2、对解空间树进行深度优先搜索; 3、再根据约束条件(总价格不能超过c)和目标函数(机器重量最小)在搜索过程中剪去多余的分支。 4、达到叶结点时记录下当前最优解。 5、实验数据n,m, ] ][ [j i w,] ][ [j i c的值由自己假设。 三、算法思想和实现【实现代码】

【实验数据】 假设机器有3个部件,每个部件可由3个供应商提供(n=3,m=3)。总价不超过7(c<=7)。 部件重量表: 部件价格表: 【运行结果】

实验结果:选择供应商1的部件1、供应商1的部件2、供应商3的部件3,有最小重量机器的重量为4,总价钱为6。 四、问题与讨论 影响回溯法效率的因素有哪些? 答:影响回溯法效率的因素主要有以下这五点: 1、产生x[k]的时间; 2、满足显约束得x[k]值的个数; 3、计算约束函数constraint的时间; 4、计算上界函数bound的时间; 5、满足约束函数和上界函数约束的所有x[k]的个数。 五、总结 这次实验的内容都很有代表性,通过上机操作实践与对问题的思考,让我更深层地领悟到了回溯算法的思想。 回溯算法的基本思路并不难理解,简单来说就是:从一条路往前走,能进则进,不能进则退回来,换一条路再试。回溯法的基本做法是深度优先搜索,是一种组织得井井

八大思维的经典案例

一、创新思维 1、在一个专门收集世界名画的美术馆,每幅画都投了一份巨额保险。可是美术馆新购进一副非常有名的画家的代表作,却没给这幅画投保险。 你知道这是为什么吗? 解答:那是一幅壁画 有六个小朋友要平均吃五块蛋糕,但不能切碎,而且任何一块蛋糕切成三块以上,你知道怎么分切这5块蛋糕吗? 解答:先把三块蛋糕各切成平均的两半,然后分给6个小朋友。然后把另外两块蛋糕分别切成三等份,再分给6个小朋友,这样每个人就得到了一个半块和1/3块。 二、发散思维 1、尽可能想象“△”和什么东西相似或相近? 解答:和“△”相似或相近的东西有:馒头、涵洞、峭石、山峰、堡垒、城门、隧道口、喷水池、橱窗、问讯窗口、尼龙秧棚、坟墓、萌芽、彩虹、乌篷船、抛物红、仙鹤戏水、镜片、电视机屏幕、枪洞、子弹头、树荫、海上日出、跳水、弯腰、插秧、拱桥、盾牌、活页木铁夹、天边浮云、英文字母“D”等等。回答得越多,发散思维的流畅程度越高。 2、古时候,有兄弟三人。大哥、二哥好吃懒做,三弟勤劳聪明。三人长大后都成了家。有一天,三兄弟在一起喝酒,大哥、二哥提议:“从现在起,我们三人说话,互相不准怀疑,否则罚米一斗。”酒后,大哥说:“你们总说我好吃懒做,现在家里那只母鸡一报晓,我就起床了……”三弟直摇头说:“哪有母鸡报晓之理?”大哥嘿嘿一笑说:“好!你不信我的话,罚米一斗。”二哥接下去说:“我没有大哥这么勤快,因此家里穷得老鼠撵得猫吱吱叫……”三弟又连连摇头,二哥得意地说:“你不信,也罚米一斗。”后来…… 三、收敛思维

1、高尔基童年在食品店干杂活,曾碰到过一位刁钻的顾客,“订九块蛋糕,但要装在四个盒子里,而且每个盒子里至少要装三块蛋糕”。 解答:高尔基的办法是:先将九个蛋糕分装在三个盒子里,每盒三块;然后再把这三个盒子一起装在一个大盒子里,用包装袋扎好。 2、你的面前摆着四种物品: 一本平装书; 一瓶百事可乐; 一根纯金项链; 一台彩色电视机。 请从上述四种物品中找出一种“与众不同”的物品;然后,再找出两两物品之间的共同之处。 解答: 平装书是唯一用纸做成的、供人阅读的物品; 可乐是唯一由液体构成、供人饮用的物品; 项链是唯一用纯金制作的、戴在身上的装饰品; 电视是唯一能把无线电波转换成声音和图像的物品。 平装书与可乐属于“价格低廉品”;平装书与电视属于“信息用品”;可乐与电视属于“诞生于现代的物品”;项链与电视属于“贵重物品”······ 四、类比思维 1、棒球:投手 篮球:得分手 B.拳击:对手 C.足球:射手 D.橄榄球:四分卫

算法分析与设计期末模拟试题

安徽大学2010-2011学年第1学期《算法分析与设计》 期末试题 押宝 (内部交流,非考试试题,学生自发交流创作,版权归作者testfudan@https://www.360docs.net/doc/ac12333993.html, 所有) 一、选择题(单选)(10*2’=20’) 1. 选择正确的组合对于 2112n +=( ) ①2()o n ② 2()O n ③2()n θ ④2()n Ω ⑤ 2()n ω A. ①③④ B. ②③④ C.③④⑤ D. ①⑤ 2. ①21()()n i i O n O n ==∑ ②2()()n O n O n = ③(log )()O n O n ? ④ 2.99993 ()n O n = ⑤2/lo g ()n n n ω=其中正确的有( ) A .5组 B.4组 C.3组 D.没有正确的 3. 2/102n n +=( ) A. 2()O n B.(2)n O C.2(2)n n O + D.2 ()o n 4. 211/n += ( )(我认为是比较不错的一道题,考试可能会出现相同的方法,用极限定义来做,最后一节课老师也讲过类似的方法) A. ()O n B.()o n C.()n Ω D.(1)O 5. 310lo g n = ( ) A.(log )O n n B. (log )O n C. 3()O n D. lo g ()n O n 6. 认真完成课后习题P5面的算法分析题1-6,里面也有我不会做的,可是有谁愿意讨论? 如果能够把以上的题目都能做对,应该就是掌握了。给自己一个奖励吧!答案(如有问题,联系我吧):1-5:BBBDB 6.做出来对对答案吧。 二、填空题 1.()2(/2)T n T n n =+????的一个渐进上界为 (答案:(log )O n n ,用迭代法) 2.()(/3)(2/3)()T n T n T n O n =++的一个渐进上界为 (答案:(log )O n n ,用递归树求解,不会的赶快看) 3.()9(/3)T n T n n =+的一个渐进紧致界为 (答案:2 ()n θ,采用迭代法或者采用主方法,不会的赶快看)

回溯法实验(0-1背包问题)

算法分析与设计实验报告第五次附加实验

附录: 完整代码(回溯法) //0-1背包问题回溯法求解 #include using namespace std; template class Knap //Knap类记录解空间树的结点信息 { template friend Typep Knapsack(Typep [],Typew [],Typew,int); private: Typep Bound(int i); //计算上界的函数 void Backtrack(int i); //回溯求最优解函数

Typew c; //背包容量 int n; //物品数 Typew *w; //物品重量数组| Typep *p; //物品价值数组 Typew cw; //当前重量 Typep cp; //当前价值 Typep bestp; //当前最后价值 }; template Typep Knapsack(Typep p[],Typew w[],Typew c,int n); //声明背包问题求解函数template inline void Swap(Type &a,Type &b); //声明交换函数 template void BubbleSort(Type a[],int n); //声明冒泡排序函数 int main() { int n ;//物品数 int c ;//背包容量 cout<<"物品个数为:"; cin>>n; cout<<"背包容量为:"; cin>>c; int *p = new int[n];//物品价值下标从1开始 int *w = new int[n];//物品重量下标从1开始 cout<<"物品重量分别为:"<>w[i]; } cout<<"物品价值分别为:"<>p[i]; } cout<<"物品重量和价值分别为:"<

贪心算法的应用

从贪心算法的定义可以看出,贪心法并不是从整体上考虑问题,它所做出的选择只是在某种意义上的局部最优解,而由问题自身的特性决定了该题运用贪心算法可以得到最优解。 我们看看下面的例子 例1 均分纸牌(NOIP2002tg) [问题描述] 有 N 堆纸牌,编号分别为 1,2,…, N。每堆上有若干张,但纸牌总数必为 N 的倍数。可以在任一堆上取若干张纸牌,然后移动。移牌规则为:在编号为 1 堆上取的纸牌,只能移到编号为 2 的堆上;在编号为 N 的堆上取的纸牌,只能移到编号为 N-1 的堆上;其他堆上取的纸牌,可以移到相邻左边或右边的堆上。现在要求找出一种移动方法,用最少的移动次数使每堆上纸牌数都一样多。例如 N=4,4 堆纸牌数分别为: ①9 ②8 ③17 ④6 移动3次可达到目的: 从③取 4 张牌放到④(9 8 13 10) -> 从③取 3 张牌放到②(9 11 10 10)-> 从②取 1 张牌放到①(10 10 10 10)。 [输入]:键盘输入文件名。 文件格式:N(N 堆纸牌,1 <= N <= 100) A1 A2 … An (N 堆纸牌,每堆纸牌初始数,l<= Ai <=10000) [输出]:输出至屏幕。格式为:所有堆均达到相等时的最少移动次数。 [输入输出样例] : 4 9 8 17 6 屏慕显示:3 算法分析:设a[i]为第i堆纸牌的张数(0<=i<=n),v为均分后每堆纸牌的张数,s为最小移到次数。 我们用贪心法,按照从左到右的顺序移动纸牌。如第i堆(0v,则将a[i]-v张纸牌从第I堆移动到第I+1堆; (2)若a[i]

最新《算法分析与设计》期末考试复习题纲(完整版)

《算法分析与设计》期末复习题 一、选择题 1.算法必须具备输入、输出和( D )等4个特性。 A.可行性和安全性 B.确定性和易读性 C.有穷性和安全性 D.有穷性和确定性 2.算法分析中,记号O表示( B ),记号Ω表示( A ) A.渐进下界 B.渐进上界 C.非紧上界 D.紧渐进界 3.假设某算法在输入规模为n时的计算时间为T(n)=3*2^n。在某台计算机上实现并 完成概算法的时间为t秒。现有另一台计算机,其运行速度为第一台的64倍,那么在这台新机器上用同一算法在t秒内能解输入规模为多大的问题?( B )解题方法:3*2^n*64=3*2^x A.n+8 B.n+6 C.n+7 D.n+5 4.设问题规模为N时,某递归算法的时间复杂度记为T(N),已知T(1)=1, T(N)=2T(N/2)+N/2,用O表示的时间复杂度为( C )。 A.O(logN) B.O(N) C.O(NlogN) D.O(N2logN) 5.直接或间接调用自身的算法称为( B )。 A.贪心算法 B.递归算法 C.迭代算法 D.回溯法 6.Fibonacci数列中,第4个和第11个数分别是( D )。 A.5,89 B.3,89 C.5,144 D.3,144 7.在有8个顶点的凸多边形的三角剖分中,恰有( B )。 A.6条弦和7个三角形 B.5条弦和6个三角形 C.6条弦和6个三角形 D.5条弦和5个三角形 8.一个问题可用动态规划算法或贪心算法求解的关键特征是问题的( B )。 A.重叠子问题 B.最优子结构性质 C.贪心选择性质 D.定义最优解 9.下列哪个问题不用贪心法求解( C )。 A.哈夫曼编码问题 B.单源最短路径问题 C.最大团问题 D.最小生成树问题 10.下列算法中通常以自底向上的方式求解最优解的是( B )。 A.备忘录法 B.动态规划法 C.贪心法 D.回溯法 11.下列算法中不能解决0/1背包问题的是( A )。 A.贪心法 B.动态规划 C.回溯法 D.分支限界法 12.下列哪个问题可以用贪心算法求解( D )。

回溯法实验(最大团问题)

算法分析与设计实验报告第七次附加实验

} } 测试结果 当输入图如下时: 当输入图如下时: 1 2 3 4 5 1 2 3 4 5

当输入图如下时: 1 2 3 4 5

附录: 完整代码(回溯法) //最大团问题回溯法求解 #include using namespace std; class Clique { friend void MaxClique(int **,int *,int ); private: void Backtrack(int i); int **a; //图的邻接矩阵 int n; //图的顶点数 int *x; //当前解 int *bestx; //当前最优解 int cn; //当前顶点数 int bestn; //当前最大顶点数 }; void Clique::Backtrack(int i) { //计算最大团 if(i>n) //到达叶子节点 { for(int j=1;j<=n;j++) bestx[j]=x[j]; bestn=cn;

cout<<"最大团:("; for(int i=1;i=bestn) { //修改一下上界函数的条件,可以得到 x[i]=0; //相同点数时的解 Backtrack(i+1); } } void MaxClique(int **a,int *v,int n) { //初始化Y Clique Y; Y.x=new int[n+1]; Y.a=a; Y.n=n; https://www.360docs.net/doc/ac12333993.html,=0; Y.bestn=0; Y.bestx=v; Y.Backtrack(1); delete [] Y.x; cout<<"最大团的顶点数:"<

相关文档
最新文档