Ⅰ 求数据结构形式的汉诺塔源代码
●汉诺塔算法的递归实现C++源代码
#include <fstream>
#include <iostream>
using namespace std;
ofstream fout("out.txt");
void Move(int n,char x,char y)
{
fout<<"把"<<n<<"号从"<<x<<"挪动到"<<y<<endl;
}
void Hannoi(int n,char a,char b,char c)
{
if(n==1)
Move(1,a,c);
else
{
Hannoi(n-1,a,c,b);
Move(n,a,c);
Hannoi(n-1,b,a,c);
}
}
int main()
{
fout<<"以下是7层汉诺塔的解法:"<<endl;
Hannoi(7,'a','b','c');
fout.close();
cout<<"输出完毕!"<<endl;
return 0;
}●汉诺塔算法的递归实现C源代码:
#include<stdio.h>
void hanoi(int n,char A,char B,char C)
{
if(n==1)
{
printf("Move disk %d from %c to %c\n",n,A,C);
}
else
{
hanoi(n-1,A,C,B);
printf("Move disk %d from %c to %c\n",n,A,C);
hanoi(n-1,B,A,C);
}
}
main()
{
int n;
printf("请输入数字n以解决n阶汉诺塔问题:\n");
scanf("%d",&n);
hanoi(n,'A','B','C');
}
●汉诺塔算法的非递归实现C++源代码
#include <iostream>
using namespace std;
//圆盘的个数最多为64
const int MAX = 64;
//用来表示每根柱子的信息
struct st{
int s[MAX]; //柱子上的圆盘存储情况
int top; //栈顶,用来最上面的圆盘
char name; //柱子的名字,可以是A,B,C中的一个
int Top()//取栈顶元素
{
return s[top];
}
int Pop()//出栈
{
return s[top--];
}
void Push(int x)//入栈
{
s[++top] = x;
}
} ;
long Pow(int x, int y); //计算x^y
void Creat(st ta[], int n); //给结构数组设置初值
void Hannuota(st ta[], long max); //移动汉诺塔的主要函数
int main(void)
{
int n;
cin >> n; //输入圆盘的个数
st ta[3]; //三根柱子的信息用结构数组存储
Creat(ta, n); //给结构数组设置初值
long max = Pow(2, n) - 1;//动的次数应等于2^n - 1
Hannuota(ta, max);//移动汉诺塔的主要函数
system("pause");
return 0;
}
void Creat(st ta[], int n)
{
ta[0].name = 'A';
ta[0].top = n-1;
//把所有的圆盘按从大到小的顺序放在柱子A上
for (int i=0; i<n; i++)
ta[0].s[i] = n - i;
//柱子B,C上开始没有没有圆盘
ta[1].top = ta[2].top = 0;
for (int i=0; i<n; i++)
ta[1].s[i] = ta[2].s[i] = 0;
//若n为偶数,按顺时针方向依次摆放 A B C
if (n%2 == 0)
{
ta[1].name = 'B';
ta[2].name = 'C';
}
else //若n为奇数,按顺时针方向依次摆放 A C B
{
ta[1].name = 'C';
ta[2].name = 'B';
}
}
long Pow(int x, int y)
{
long sum = 1;
for (int i=0; i<y; i++)
sum *= x;
return sum;
}
void Hannuota(st ta[], long max)
{
int k = 0; //累计移动的次数
int i = 0;
int ch;
while (k < max)
{
//按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
ch = ta[i%3].Pop();
ta[(i+1)%3].Push(ch);
cout << ++k << ": " <<
"Move disk " << ch << " from " << ta[i%3].name <<
" to " << ta[(i+1)%3].name << endl;
i++;
//把另外两根柱子上可以移动的圆盘移动到新的柱子上
if (k < max)
{ //把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
if (ta[(i+1)%3].Top() == 0 ||
ta[(i-1)%3].Top() > 0 &&
ta[(i+1)%3].Top() > ta[(i-1)%3].Top())
{
ch = ta[(i-1)%3].Pop();
ta[(i+1)%3].Push(ch);
cout << ++k << ": " << "Move disk "
<< ch << " from " << ta[(i-1)%3].name
<< " to " << ta[(i+1)%3].name << endl;
}
else
{
ch = ta[(i+1)%3].Pop();
ta[(i-1)%3].Push(ch);
cout << ++k << ": " << "Move disk "
<< ch << " from " << ta[(i+1)%3].name
<< " to " << ta[(i-1)%3].name << endl;
}
}
}
}
Ⅱ 起爆点指标和选股公式都是什么意思
一、 股票起爆点的基本含义
一般来说,是股票开始涨的时候,但因为它是爆炸性的上涨,所以被称为起爆点。
(一)起爆点的圆盘特征
交易量扩大。长期融资后,主力逐渐控制盘面。一般来说,爆破前成交量会放大。
1.试探性引体向上。在爆发开始之前,主力一般会进行试探性的拉升,试探市场的追赶意愿。
2.进行最后一道洗菜。这时股价往往波动较大,大阴大阳交替出现,以彻底摆脱下面的盘面。
3.突然大量拉升,迅速离开成本区。它的凶猛让人敢看敢摸。连续交易是这种形态突破后最强的表现。 二、注意两个启动点 第一个爆点是短线操作的第一个也是最好的买入点。起点是,经过长时间的横向盘整,主力已经完成募资和洗盘,处于向上突破的临界点。
(二)起爆点的干预方法:
1.突破股价成交量新高的第一条阳线。
2.第一次拦回后股价在大放量突破新高(一般在领口附近介入)。 第二个启动点(即第二个最佳买入点)——股价从第一个破发点上涨,进入另一个区间。这时由于利润空间太大,主力会进行强制洗盘。经过一段时间的盘整,均线系统会逐渐上移,使得市场的持有成本上移并趋于一致。在第二波主升浪开始之前,就像最后一个破发点一样,主力会迈出最后一步这种凶猛的洗盘会把那些不坚定的人从风车上推下来,然后向上突破放量,股价从地面上涨。其上升力度一般不低于前一个爆点,甚至进入主上升波。
3.如果不回调,说明该股很可能进入主升阶段。这时候要根据交易量来决定。如果成交量萎缩上涨,意味着主力需要进一步提高股价,可以适量买入;如果成交量异常放大,连续几天单日换手率超过30%,则需谨慎,这很可能是主力出货的信号。
二、 选股公式
简单说就是在股票软件里,根据自己的条件要求编写一个选股公式,让电脑自动选出符合你条件要求的股票。
拓展资料:
一、如何抓住起爆点
市场里面有句说的好,会买的是徒弟,会卖的师傅,会空仓的是师爷,但是我要说的是熊市里面会买是第一要素。 那么我们如何才是最好的介入时机呢? 我将为大家揭晓一种胜算非常高的买入技巧: 在市场的起爆点买入 买入时机要有一下几大要素: 1:前一天缩量下跌,均线不要空头排列; 2:第一天放量上涨,收阳线。但是不要出现非常长的上影线, 3:不是一口气冲上涨停板的不要追高买,在分时的黄线,均价附近买入。分批买进; 以上几点,是基本要素,只要按照这样的方法买入,后续短期都会上涨,基本很难亏钱。
二、炒股应关注两个起爆点
1.短线操作的第一个买点,也是最佳买入点。该起爆点就是股票经过长时间的横盘整理,主力已经完成吸筹和洗盘,处于向上突破的临界点。
2.第二起爆点(也即第二最佳买入点)------股价脱离第一起爆点后上升进入另区间。这时,由于获利盘太多,主力会进行强制洗盘。经过一段时间的整理后,均线系统逐步上移,使市场的持股成本上移并趋于一致。在第二波主升浪展开前,犹如上一起暴点一样,主力会做最后一次凶猛的洗盘,将不坚定者赶下跟风车,然后带量向上突破,股价拔地而起,其上涨力度一般不亚于上一起爆点甚至进入主升浪。
三、第二起爆点的介入方法
1.在股价放量向上突破创出新高的第一根阳线介入。
2.在股价放量向上突破创出新高后的第一次回挡(一般在颈线位附近介入)。
3.如果不回挡,则说明该股很可能是进入主升阶段,这时要视成交量的状况再作决定。如果缩量上涨则说明主力要进一步拉高股价,可以适量买入;如果成交量异常放大而且连续几天单日换手率超过30%则应谨慎,很可能是主力出货的信号。
Ⅲ 水质监测的常规五项指标是哪些
污水的五个检测项目一般是pH值检测、SS项目检测、氨氮检测、BOD检测和COD检测。
这些项目的测试内容如下:
1、PH值检测:指pH测试,也指氢离子浓度指数,即污水中氢离子总数与总物质含量的比值。
2、SS项目检测:指水中悬浮物的检测,包括不溶性无机物、有机物、砂、粘土、微生物等。悬浮物含量是衡量水体污染程度的重要指标之一。
3、氨氮检测:氨氮是指水中游离氨和铵离子形式的氮,可导致水体富营养化。它是水体中的主要OD污染物,对鱼类和某些水生生物具有毒性。
4、BOD检测:指生化需氧量的检测。生化需氧量是指微生物在一定时间内分解一定水量水所消耗的溶解氧量,是反映水体中有机污染物含量的重要指标。
5、COD检测:化学需氧量检测是测定水样中需要氧化的还原性物质的量的化学方法,可以通过减少水中的物质来反映污染程度。
污水分类:
1、生活污水
生活污水是人类在日常生活中使用过的,并被生活废料所污染的水。其水质、水量随季节而变化,一般夏季用水相对较多,浓度低;冬季相应量少,浓度高。生活污水一般不含有毒物质,但是它有适合微生物繁殖的条件,含有大量的病原体,从卫生角度来看有一定的危害性。
2、工业废水
工业废水是在工矿生产活动中产生的废水。工业废水可分为生产污水与生产废水。生产污水是指在生产过程中形成、并被生产原料、半成品或成品等原料所污染,也包括热污染(指生产过程中产生的、水温超过60℃的水);生产废水是指在生产过程中形成,但未直接参与生产工艺、未被生产原料、半成品或成品等原料所污染或只是温度少有上升的水。生
产污水需要进行净化处理;生产废水不需要净化处理或仅需做简单的处理,如冷却处理。生活污水与生产污水的混合污水称为城市污水。
3、初期雨水
被污染的雨水主要是指初期雨水。由于初期雨水冲刷了地表的各种污染物,污染程度很高,故宜作净化处理。
4、水体受污染的原因:
人类生产活动造成的水体污染中,工业引起的水体污染最严重。如工业废水,它含污染物多,成分复杂,不仅在水中不易净化,而且处理也比较困难。
工业废水,是工业污染引起水体污染的最重要的原因。它占工业排出的污染物的大部分。工业废水所含的污染物因工厂种类不同而千差万别,即使是同类工厂,生产过程不同,其所含污染物的质和量也不一样。工业除了排出的废水直接注入水体引起污染外,固体废物和废气也会污染水体。
以上内容参考:网络-污水
Ⅳ 汉诺塔的其他相关
如果移动一个圆盘需要1秒钟的话,等到64个圆盘全部重新落在一起,宇宙被毁灭是什么时候呢?
让我们来考虑一下64个圆盘重新摞好需要移动多少次吧。1个的时候当然是1次,2个的时候是3次,3个的时候就用了7次......这实在是太累了
因此让我们逻辑性的思考一下吧。
3个的时候能够移动最大的3盘时如图所示。
到此为止用了7次。
接下来如右图,在上面再放上3个圆盘时还要用7次(把3个圆盘重新放在一起需要的次数)。
因此,4个的时候是
“3个圆盘重新摞在一起的次数”+1次+“3个圆盘重新摞在一起需要的次数”
=2x“3个圆盘重新摞在一起的次数”+1次
=15次。
那么,n个的时候是
2x“(n-1)个圆盘重新摞在一起的次数”+1次。
由于1 个的时候是1次,结果n个的时候为(2的n次方减1)次。
1个圆盘的时候 2的1次方减1
2个圆盘的时候 2的2次方减1
3个圆盘的时候 2的3次方减1
4个圆盘的时候 2的4次方减1
5个圆盘的时候 2的5次方减1
........
n个圆盘的时候 2的n次方减1
也就是说,n=64的时候是(2的64次方减1)次。
因此,如果移动一个圆盘需要1秒的话,
宇宙的寿命=2的64次方减1(秒)
2的64次方减1到底有多大呢?动动计算器,答案是一个二十位的数字约是
1.84467440*10^19
用一年=60秒x60分x24小时x365天来算的话,大约有5800亿年吧。
太阳及其行星形成于50亿年前,其寿命约为100亿年。
汉诺塔问题在数学界有很高的研究价值,而且至今还在被一些数学家们所研究。
也是我们所喜欢玩的一种益智游戏,它可以帮助开发智力,激发我们的思维。 有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,请问至少需要多少次移动,设移动次数为H(n)。
首先我们肯定是把上面n-1个盘子移动到柱子C上,然后把最大的一块放在B上,最后把C上的所有盘子移动到B上,由此我们得出表达式:
H⑴ = 1
H(n) = 2*H(n-1)+1 (n>1)
那么我们很快就能得到H(n)的一般式:
H(n) = 2^n - 1 (n>0)
并且这种方法的确是最少次数的,证明非常简单,可以尝试从2个盘子的移动开始证,你可以试试。
进一步加深问题(解法原创*_*):
假如现在每种大小的盘子都有两个,并且是相邻的,设盘子个数为2n,问:⑴假如不考虑相同大小盘子的上下要多少次移动,设移动次数为J(n);⑵只要保证到最后B上的相同大小盘子顺序与A上时相同,需要多少次移动,设移动次数为K(n)。
⑴中的移动相当于是把前一个问题中的每个盘子多移动一次,也就是:
J(n) = 2*H(n) = 2*(2^n - 1) = 2^(n+1)-2
在分析⑵之前
,我们来说明一个现象,假如A柱子上有两个大小相同的盘子,上面一个是黑色的,下面一个是白色的,我们把两个盘子移动到B上,需要两次,盘子顺序将变成黑的在下,白的在上,然后再把B上的盘子移动到C上,需要两次,盘子顺序将与A上时相同,由此我们归纳出当相邻两个盘子都移动偶数次时,盘子顺序将不变,否则上下颠倒。
现在回到最开始的问题,n个盘子移动,上方的n-1个盘子总移动次数为2*H(n-1),所以上方n-1个盘子的移动次数必定为偶数次,最后一个盘子移动次数为1次。
讨论问题⑵,
综上两点,可以得出,要把A上2n个盘子移动到B上,首先可以得出上方的2n-2个盘子必定移动偶数次,所以顺序不变,移动次数为:
J(n-1) = 2^n-2
然后再移动倒数第二个盘子,移动次数为2*J(n-1)+1 = 2^(n+1)-3,
最后移动最底下一个盘子,所以总的移动次数为:
K(n) = 2*(2*J(n-1)+1)+1 = 2*(2^(n+1)-3)+1 = 2^(n+2)-5
开天辟地的神勃拉玛(和中国的盘古差不多的神吧)在一个庙里留下了三根金刚石的棒,第一根上面套着64个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从这根棒搬到另一根棒上,规定可利用中间的一根棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。计算结果非常恐怖(移动圆片的次数)大约是1.84467440*10^19,众僧们即便是耗尽毕生精力也不可能完成金片的移动了。 其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n – 1(有兴趣的可以自己证明试试看)。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C;
若n为奇数,按顺时针方向依次摆放 A C B。
⑴按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。
⑵接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。
⑶反复进行⑴⑵操作,最后就能按规定完成汉诺塔的移动。
所以结果非常简单,就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C
汉诺塔问题也是程序设计中的经典递归问题,下面我们将给出递归和非递归的不同实现源代码。
Ⅳ 汉诺塔怎么玩
一位美国学者发现的特别简单的方法:只要轮流用两次如下方法就可以了。
把三根柱子按顺序排成“品”字型,把所有圆盘按从大到小的顺序放于柱子A上,根据圆盘数量来确定柱子排放的顺序:
n若为偶数的话,顺时针方向依次摆放为:ABC;而n若为奇数的话,就按顺时针方向依次摆放为:ACB。这样经过反复多次的测试,最后就可以按照规定完成汉诺塔的移动。
因此很简单的,结果就是按照移动规则向一个方向移动金片:
如3阶汉诺塔的移动:A→C,A→B,C→B,A→C,B→A,B→C,A→C。
由来
法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。
不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
Ⅵ android的自定圆盘菜单怎么做
1、通用模式
上图是图片加文字,如果我想换成按钮呢,或者我只需要图片。这里就需要定制。怎么办呢,我采用了适配模式,大家都还记得 ListView的用法,我这里也借鉴了一下:
public void setAdapter(ListAdapter mAdapter) { this.mAdapter = mAdapter;
}123
这样就可以实现Menu的高度定制。
2、构建菜单项
代码参考buildMenuItems(),对mAdapter遍历获取子View,添加点击事件,调用addView()添加到ViewGroup,这个时候系统就会调用onMeasure()对子View计算大小。
3、计算item大小
代码参考measureMyself()和measureChildViews(),确定每个item的尺寸大小。
4、item布局
首先计算item(x,y)距离圆心的长度,我画了一个草图:
需要重写onTouchEvent()方法,并把返回值改为true。处理手势按下(ACTION_DOWN),抬起(ACTION_UP)的状态。
首先我们要判断手指按下是否在阴影局域内。注意手指按下是指尖局域与屏幕接触,并不是一点,所以有误差。
x = event.getX();
y = event.getY();if ((x - 圆心x) * (x - 圆心x) + (y - 圆心y) * (y - 圆心y) < (圆心x+ 误差) * (圆心y+ 误差)) {
isRange = true;
}12345
然后我们要计算运动的速度,我刚开始的想法是用重力加速度,非常感谢我同事小贾,他给了我更好的意见:速度=距离/时间。
ACTION_DOWN:
lastTouchTime = System.currentTimeMillis();1
ACTION_UP:
long timeStamp = System.currentTimeMillis() - lastTouchTime;float distance = (float) Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)); float speed = distance / timeStamp;123
然后我们通过对比手指按下的x的坐标,和抬起x的坐标,来判断用户是向左滑,还是右滑。
if (x1 - x > 0) {
isLeft = false;
} else {
isLeft = true;
}12345
最后通过handler来改变每次运动的角度,使Menu很自然的旋转了起来:
if (isLeft) { //向左转动
offsetRotation -= ANGLE;
} else { //向右转动
offsetRotation += ANGLE;
} //速度衰减
speed -= SPEED_ATTENUATION;
invalidate();//重绘
handler.sendEmptyMessageDelayed(EMPTY_MESSAGE, 50);1234567891011
使用
1、xml布局
<com.github.ws.viewdemo.widget.CircleMenuLayout
android:id="@+id/cm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f0f0f0">
</com.github.ws.viewdemo.widget.CircleMenuLayout>1234567
2、class文件
circleMenuLayout.setAdapter(new MyAdapter());
circleMenuLayout.setOnItemClickListener(new CircleMenuLayout.OnItemClickListener() {
@Override public void onItemClickListener(View v, int position) {
Toast.makeText(MainActivity.this, mList.get(position).text + "", Toast.LENGTH_SHORT).show();
}
});12345678
源码我已上传到github,地址https://github.com/HpWens/ViewDemo,再一次感谢大家的关注。