8枚硬币问题(减治法) c语言

合集下载

减治法

减治法
原问题 的规模是n
子问题 的规模是n/2 子问题的解
原问题的解
图5.1 减治法的典型情况(减半技术)
对于给定的整数a和非负整数n,计算an的值。
利用减治法,如果n=1,可以简单地返回a的值,如果n是偶数并且n>1,可 以把该问题的规模减半,即计算an/2的值,而且规模为n的解an和规模减半 的解an/2之间具有明显的对应关系:an=(an/2)2,如果n是奇数并且n>1,可 以先用偶指数的规则计算a(n-1),再把结果乘以a。所以,应用减治技术得到 如下计算方法:
排序问题中的减治法
堆排序
选择问题
堆排序

28 25 36 18 32 28 36 25 18 16 32 25 16 36 25 18 16 36 28 32
28
18 16
32
堆排序是利用堆(假设利用大根堆)的特性进 行排序的方法,其基本思想是:首先将待排序 的记录序列构造成一个堆,此时,选出了堆中 所有记录的最大者即堆顶记录,然后将它从堆 中移走(通常将堆顶记录和堆中最后一个记录 交换),并将剩余的记录再调整成堆,这样又 找出了次大的记录,以此类推,直到堆中只有 一个记录为止。
n 1 n 1
查找问题中的减治法
折半查找
二叉查找树
折半查找
在有序表{ 7, 14, 18, 21, 23, 29, 31, 35, 38, 42, 46, 49, 52 }中查找值为14的 记录的过程如图所示。
0 1
7
2
14
3
18
4
21
5
23
6
29
7
31
8
35
9
38
10
42

八枚银币游戏算法

八枚银币游戏算法

/*八枚银币问题现有八枚银币a b c d e f g h,已知其中一枚是假币,其重量不同于真币,但不知是较轻或较重,如何使用天平以最少的比较次数,决定出哪枚是假币,并得知假币比真币较轻或较重。

*/declarea number;b number;c number;d number;e number;f number;g number;h number;x integer default 0;begina := &a;b := &b;c := &c;d := &d;e := &e;f := &f;g := &g;h := &h;if ((a + b) = (c + d)) thenx := x + 1;if (e = f) thenx := x + 1;if (g = e) thenx := x + 1;if (g < h) thenx := x + 1;dbms_output.put_line('h = ' || h || ',较重!称了' || x || '次!');elsex := x + 1;dbms_output.put_line('h = ' || h || ',较轻!称了' || x || '次!');end if;elsex := x + 1;if (g > h) thenx := x + 1;dbms_output.put_line('g = ' || g || ',较重!称了' || x || '次!');elsex := x + 1;dbms_output.put_line('g = ' || g || ',较轻!称了' || x || '次!');end if;end if;elsex := x + 1;if (e = g) thenx := x + 1;if (e < f) thendbms_output.put_line('f = ' || f || ',较重!称了' || x || '次!');elsedbms_output.put_line('f = ' || f || ',较轻!称了' || x || '次!');end if;elsex := x + 1;if (e > f) thendbms_output.put_line('e = ' || e || ',较重!称了' || x || '次!');elsedbms_output.put_line('e = ' || e || ',较轻!称了' || x || '次!');end if;end if;end if;elsex := x + 1;if (a = b) thenx := x + 1;if (c = a) thenx := x + 1;if (c < d) thendbms_output.put_line('d = ' || d || ',较重!称了' || x || '次!');elsedbms_output.put_line('d = ' || d || ',较轻!称了' || x || '次!');end if;elsex := x + 1;if (c > d) thendbms_output.put_line('c = ' || c || ',较重!称了' || x || '次!');elsedbms_output.put_line('c = ' || c || ',较轻!称了' || x || '次!');end if;end if;elsex := x + 1;if (a = c) thenx := x + 1;if (a < b) thendbms_output.put_line('b = ' || b || ',较重!称了' || x || '次!');elsedbms_output.put_line('b = ' || b || ',较轻!称了' || x || '次!');end if;elsex := x + 1;if (a > b) thendbms_output.put_line('a = ' || a || ',较重!称了' || x || '次!');elsedbms_output.put_line('a = ' || a || ',较轻!称了' || x || '次!');end if;end if;end if;end if;end;/*提示:该算法经典之处在于二叉树使用巧妙,每称一次就排除一半*/。

算法笔记_004:8枚硬币问题【减治法】

算法笔记_004:8枚硬币问题【减治法】

算法笔记_004:8枚硬币问题【减治法】⽬录1 问题描述(1)实验题⽬在8枚外观相同的硬币中,有⼀枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相⽐较轻还是较重。

可以通过⼀架天平来任意⽐较两组硬币,设计⼀个⾼效的算法来检测这枚假币。

(2)实验⽬的1)深刻理解并掌握减治法的设计思想并理解它与分治法的区别;2)提⾼应⽤减治法设计算法的技能。

3)理解这样⼀个观点:建⽴正确的模型对于问题的求解是⾮常重要的。

(3)实验要求1)设计减治算法实现8枚硬币问题;2)设计实验程序,考察⽤减治技术设计的算法是否⾼效;3)扩展算法,使之能处理n枚硬币中有⼀枚假币的问题。

(4)实现提⽰假设⽤⼀个数组B[n]表⽰硬币,元素B[i]中存放第i枚硬币的重量,其中n-1个元素的值都是相同的,只有⼀个元素与其他元素值不同,则当n=8时即代表8枚硬币问题。

由于8枚硬币问题限制只允许使⽤天平⽐较轻重,所以,算法中只能出现元素相加和⽐较的语句。

2 解决⽅案2.1 减治法原理叙述在说减法法原理之前,我们先来简单看看分治法原理:分治法是把⼀个⼤问题划分为若⼲⼦问题,分别求解⼦问题,然后再把⼦问题的解进⾏合并得到原问题的解。

⽽减治法同样是把⼤问题分解成为若⼲个⼦问题,但是这些⼦问题不需要分别求解,只需求解其中的⼀个⼦问题,也⽆需对⼦问题进⾏合并。

换种说法,可以说减治法是退化的分治法。

减治法原理正式描述:减治法(reduce and conquer method)将原问题的解分解为若⼲个⼦问题,并且原问题的解与⼦问题的解之间存在某种确定关系,如果原问题的规模为n,则⼦问题的规模通常是n/2 或n-1。

2.2 8枚硬币规模解法求解思路:(1)⾸先输⼊8枚硬币重量,存放在⼀个长度为8的⼀维数组中。

(2)定义a,b,c,d,e,f,g,h⼋个变量,分别对应⼀枚硬币的重量。

然后把这8枚硬币分成三组,分别为abc(abc = a+b+c)、def(def =d+e+f)、gh。

八枚硬币的判定树

八枚硬币的判定树

树的应用举例——八枚硬币问题设有八枚硬币,分别表示为a,b,c,d,e,f,g,h,其中有且仅有一枚硬币是假币,并且假币的重量与真币的重量不同,可能轻,也可能重。

现要求以天平为工具,用最少的比较次数挑选出假币,并同时确定这枚假币的重量比其它真币是轻还是重。

问题的解决是经过一系列的判断,这些判断构成了树结构,可以用判定树来描述这个判定过程。

解决这个问题的最自然的想法就是把硬币分成两组,也就是一分为二。

但是,如果一分为三的话,会获得更少的比较次数。

从八枚硬币中任取六枚a,b,c,d,e,f,在天平两端各放三枚进行比较。

假设a,b,c三枚放在天平的一端,d,e,f三枚放在天平的另一端,可能出现三种比较结果:⑴a+b+c > d+e+f⑵a+b+c=d+e+f⑶a+b+c < d+e+f若a+b+c >d+e+f,可以肯定这六枚硬币中必有一枚为假币,同时也说明,为真币。

这时可将天平两端各去掉一枚硬币,假设去掉和,同时将天平两端的硬币各换一枚,假设硬币,作了互换,然后进行第二次比较,比较的结果同样可能有三种:①a+e>d+b:这种情况表明天平两端去掉硬币c,f且硬币b,e互换后,天平两端的轻重关系保持不变,从而说明了假币必然是a,d中的一个,这时我们只要用一枚真币(例如h)和a进行比较,就能找出假币。

若a>h,则a是较重的假币;若a=h,则d为较轻的假币;不可能出现a②a+e=d+b:此时天平两端由不平衡变为平衡,表明假币一定在去掉的两枚硬币c,f中,同样用一枚真币(例如h)和c进行比较,若c>h,则c是较重的假币;若c=h,则f为较轻的假币;不可能出现c③a+e:此时表明由于两枚硬币b,e的对换,引起了两端轻重关系的改变,那么可以肯定b或e中有一枚是假币,同样用一枚真币(例如h)和b进行比较,若b>h,则b是较重的假币;若b=h,则e为较轻的假币;不可能出现b 对于结果⑵和⑶的情况,可按照上述方法作类似的分析。

c语言八皇后问题程序设计

c语言八皇后问题程序设计

2014年春季学期《C项目设计》报告题目:八皇后问题学号:092213112姓名:刘泽中组名:1指导教师:宋东兴日期:2014.05.15目录正文 (3)1.问题描述 (3)2. 总体设计与分析 (3)3. 相关代码 (5)4. 调试分析 (9)5.软件使用说明书 (11)总结 (11)附录:部分原程序代码 (12)一、问题描述1.八皇后问题:是一个古老而著名的问题。

该问题是十九世纪著名的数学家高斯1850年提出:在8×8棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法?2.解决八皇后问题的关键在于:(1)找到合理的数据结构存放棋子的摆放位置。

(2)要有合理的冲突检查算法。

采用的方法是,先把8个棋子摆在棋盘上,每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解决方案。

由于皇后的摆放位置不能通过某种公式来确定,因此对于每个皇后的摆放位置都要进行试探和纠正,这就是“回溯”的思想。

在8个皇后未放置完成前,每行摆放一个皇后,摆放第i个皇后和第i+1个皇后的试探方法是相同的,因此完全可以采用递归的方法来处理。

二、总体设计与分析1.设计效果画一个8*8的国际象棋盘,在棋盘某一位置上放一棋子,并让它按从左到右的方向自动运动,用户可以使用光标键调整棋子运动的方向,找出所有可能的摆放方案,将包含指定的棋子的(如3行4列)摆放方案找出并显示出来。

2.、总体设计程序总体分为两大块:(1)八皇后摆法的寻找;(2)棋盘及棋子的设计。

3、详细模块(1)八皇后摆法的寻找:int chess[8][8]={0}; //二维数组表示8*8棋盘,全部清0,(0代表该位没有放棋子)void queen(int i,int n){ //i表示从第i行起为后续棋子选择合适位置,n代表n*n棋盘if(i==n)output(n); //输出棋盘当前布局;else{for(j=0;j<n;j++){ //每行可能有n个摆放位置chess[i][j] = 1; //在第i行,j列上放一棋子if(!canAttack(i,j)) //如果当前布局合法,不受前i-1行的攻击queen(i+1,n); //递归摆放i+1行chess[i][j] = 0; //移走第i行,j列的棋子}}}int canAttack(int i,int j){ //判断0到i-1行已摆放的棋子,对[i,j]位置是否可以攻击for(m=0;m<i;m++){for(n=0;n<8;n++){if(chess[m][n]==1){if(m==i||n==j) return 1;if(m+n==i+j || m-n==i-j) return 1;}}}return 0;}void output(){ //输出一组解,即打印出8个皇后的坐标for(int i=0;i<8;i++){for(int j=0;j<8;j++){if(chess[i][j]==1){printf("(%d,%d)",i,j);}}}printf(“\n”);}int main(){queen(0,8);return 0;}(2)棋盘及棋子的设计:void drawBlock(int i,int j){ //棋盘的设计(每一个小方块)int x0,y0,x1,y1;x0=ORGX+j*W;y0=ORGY+i*H;x1=x0+W-1;y1=y0+H-1;setcolor(WHITE);rectangle(x0,y0,x1,y1);setfillstyle(1,LIGHTGRAY);floodfill(x0+1,y0+1,WHITE);setcolor(WHITE);line(x0,y0,x1,y0);line(x0,y0,x0,y1);setcolor(BLACK);line(x1,y0,x1,y1);line(x0,y1,x1,y1);}void drawBall(Ball ball){ //棋子的设计int x0,y0;x0=ball.startX+ball.c*ball.w+ball.w/2;y0=ball.startY+ball.r*ball.h+ball.h/2;setcolor(RED);setfillstyle(1,RED);fillellipse(x0,y0,10,10);}4.程序设计思路:先设计程序,找到八皇后的摆放位置,方法是:先把8个棋子摆在棋盘上,每行摆一个,然后去检查这种摆放是否有冲突,如果没有冲突,即找到了一种解决方案。

C++程序 最少硬币问题

C++程序 最少硬币问题

//
main.cpp
#include "LeastCoins.h" int main() { LeastCoins LC; LC.run(); return 0; }
{ outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<X<<endl; j-=X*T[i]; } else { outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<(X-1)<<endl; j-=(X-1)*T[i]; } } outputFile<<setw(3)<<T[i]<<setw(3)<<" "<<setw(3)<<(j/T[1])<<endl; }
要找回
钱数是 j 需要硬币数的 最少个
//
LeastCoins.cpp <iostream.h> <fstream.h> <cstdlib> <iomanip.h>
#include #include #include #include
#include "LeastCoins.h" #define N 10 // 根据实际问题规模的大小 来初始化 ifstream inputFile("input.txt",ios::out); ofstream outputFile("output.txt",ios::out);

8枚硬币问题(减治法) c语言

8枚硬币问题(减治法) c语言
{
sum_a+=a[j];
j++;
}
if(sum_a!=sum_b)
{
sum_a=0;//a,b数组前两个数据相加比较大小
j=0;
while(j<2)
{
sum_a=a[j]+sum_a;
j++;
}
j=0;
sum_b=0;
while(j<2)
{
sum_b=b[j]+sum_b;
j++;
}
if(sum_a==sum_b)//找到数据在所输入数据的第3,或6位置
4.具体实现
(1)运行结果:
(2)具体程序实现:
#include<stdio.h>
#define N 8
int false_coin(int coin[]);
int main(void)
{
int coin[N];
int i=0;
printf("8枚硬币问题,0代表假,1代表真,请输入8个0或1数字,并且只存在一个假硬币:\n");
j=0;
while(j<2)
{
sum_a=a[j]+sum_a;
j++;
}
j=0;
sum_b=0;
while(j<2)
{
sum_b=b[j]+sum_b;
j++;
}
if(sum_a>sum_b)
flag_2=1;
else
flag_2=0;
if(flag_1==flag_2)
{
if(a[0]==a[1])

C++程序初级案例及答案参考

C++程序初级案例及答案参考

cout<<"请输入经纪人的底薪:";
cin>>base;
cout<<"请输入经纪人的工龄:";
cin>>seniority;
cout<<"请输入经纪人的月销售额:";
cin>>sale;
cout<<"该经纪人的月薪为:"<<fun(base,seniority,sale)<<endl;retu Nhomakorabean 0;
change=change%50; cout<<"找给顾客的壹角硬币个数为:"<<change/10<<endl;
change=change%10; cout<<"找给顾客的伍分硬币个数为:"<<change/5<<endl;
change=change%5; cout<<"找给顾客的贰分硬币个数为:"<<change/2<<endl;
//定义存放乘法结果的变量 u 并赋初值 //定义循环变量并赋初值
(四) 循环条件的嵌套
1.写出完整的程序,实现:输入密码,如果等于 1234,则显示“loading···”,并退出循 环;否则显示“input again!”。如果输入超过三次,则退出循环并结束程序。(要用到 break) 示例: 1) 密码输入 #include<iostream> using namespace std; int main() { int password; for(int i=0;i<3;i++) {
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
j++;
}
j=0;
while(j<=1)
{c[j]=coin[j+6];j++;}
j=0;
while(j<=2)//两边数组求和
{
sum_b+=b[j];
j++;
}
j=0;
while(j<=2)
{
sum_a+=a[j];
j++;
}
if(sum_a!=sum_b)
{
sum_a=0;//a,b数组前两个数据相加比较大小
j++;
}
j=0;
sum_b=0;
while(j<2)
{
sum_b=b[j]+sum_b;
j++;
}
if(sum_a>sum_b)
flag_2=1;
else
flag_2=0;
if(flag_1==flag_2)
{
if(a[0]==a[1])
return 4;
else
return 1;
}
else
{
temp=a[1];
3.实验要求
(1)设计减治算法实现8枚硬币问题;
(2)设计实验程序,考察用减治技术的算法是否高效;
(3)扩展算法,使之能处理n枚硬币中有1枚假币的问题。
4.具体实现
(1)运行结果:
(2)具体程序实现:
#include<stdio.h>
#define N 8
int false_coin(int coin[]);
}
int false_coin(int coin[])
{
int a[N],b[N],c[N],temp;
int j=0,sum_a=0,sum_b=0,flag_1,flag_2;
while(j<=2)//把8个硬币分配成a,b,c分别为3,3,2
{
a[j]=coin[j];
b[j]=coin[j+3];
}
else
{
if(sum_a>sum_b)//flag标志交换数后两边数组和是否相等
flag_1=1;
else
flag_1=0;
temp=a[1];
a[1]=b[1];
b[1]=temp;
sum_a=0;//a,b数组前两个数据相加比较大小
j=0;
while(j<2)
{
sum_a=a[j]+sum_a;
int main(void)
{
int coin[N];
int i=0;
printf("8枚硬币问题,0代表假,1代表真,请输入8个0或1数字,并且只存在一个假硬币:\n");
while(i<8)
{scanf("%d",&coin[i]);i++;
}
i=false_coin(coin);
printf("\n第%d个位置是假硬币",i);
a[1]=b[1];
b[1]=temp;
if(a[0]==a[1])
return 5;
else
return 2;
}
}
}
else
{
if(c[0]==a[0])
return 8;
ห้องสมุดไป่ตู้else
return 7;
}
}
5.实验心得
从开学到现在第一次完整的运行出正确结果,以前运行都是错误结果!程序中发现自己基础语法不扎实,数组作为参数传递时使用错误,数组输入出问题,还有不会使用单步运行,程序写完后,不管输入怎么样的输出结果就永远是在第3这个位置停留。最后加入自己写的相应的代码后,可以发现程序中的变量问题出现在哪里,程序里面的问题终于被找到!
实验项目——8枚硬币问题
1.实验题目
在8枚外观相同的硬币中,有一枚是假币,并且已知假币与真币的重量不同,但不知道假币与真币相比较轻还是较重。可以通过一架天平来任意比较两组硬币,设计一个高效的算法来检测出这枚假币。
2.实验目的
(1)深刻理解并掌握减治法的设计思想;
(2)提高应用减治法设计算法的技能;
(3)理解这样一个观点:建立正确的模型对于问题的求解时非常重要的。
j=0;
while(j<2)
{
sum_a=a[j]+sum_a;
j++;
}
j=0;
sum_b=0;
while(j<2)
{
sum_b=b[j]+sum_b;
j++;
}
if(sum_a==sum_b)//找到数据在所输入数据的第3,或6位置
{
if(a[0]==a[2])
return 6;
else
return 3;
相关文档
最新文档