1.1汉诺塔问题
问题描述请看这里。
a,b,c三个圆柱,把a上面的圆盘按照小的盘子只能放在大的上面的规则通过b移动到c上(从上到下为从大到小!)。
这个问题想必在课堂上(老师会说不用考虑中间过程是怎么进行的),书上或者某处看到过,
在这里我们把64片黄金圆盘改成为n(毕竟这是个数学问题),然后设把i个盘子从a通过b移动到c上(盘)所需要的移动次数为T(i)
(1<=i&&n>=i),我来解释一下为什么要重点标记这个"设",因为在这里把i个盘子从a移动到c和a移动到b的原理是一样的(后面会用到这个解释)。
要把n个盘子移动c上,需要先将a上面的n-1个盘子移动到b上,再将第n个盘子移动到(按照上面的解释这里用了T(n-1)),then把第n个盘子放到c上(移动了1次),记住这里还没完,因为,我们还没把n-1盘子移动到c上(所以这里还有T(n-1)次,原因看解释),所以T(n)=2*T(n-1)+1 次,然后依次地推到T(1)=1,就可以通过求解下列递推式得出次数。
#include<iostream>
using namespace std;
typedef long long ll;
int count=0;
void move(ll n,char a,char c)
{
count++;
cout << count << ':' << a << "->" << c <<endl;
}
void h(ll n,char a,char b,char c)
{
if(n==1)
{
move(n,a,c);
}
else
{
h(n-1,a,c,b);
move(n,a,c);
h(n-1,b,a,c);
}
}
int main()
{
ll n=3;
// cin>>n;
h(n,'a','b','c');
return 0;
}
扩展一下:
在原来的基础下,加上一个条件:a上的盘子,不能直接移动到c上。
解法类似,先设T(i)为把i个盘子从a经过b移动到c(不直接从a移动到c)上所需要的次数,同理把i个盘子从c经过b移动到a上需要的次数为T(i)次。
步骤:
1)先把n-1个盘子从a移动到c上,次数为T(n-1);
2)再把第n个盘子移动到b上,次数为1;
3)在把n-1个盘子从c移动到a上,次数为T(n-1);
4)再把第n个盘子从b移动到c上,次数为1;
5)最后把n-1个盘子从a移动c上,次数为T(n-1)。
综上所述:
so:
#include<iostream>
using namespace std;
long long cou;
void mov(char a,char b)
{
cou++;
cout<<cou<<a<<b<<endl;
}
void h(int n,char a,char b,char c)
{
if(n==1)
{
mov(a,b);
mov(b,c);
}
else
{
h(n-1,a,b,c);
mov(a,b);
h(n-1,c,b,a);
mov(b,c);
h(n-1,a,b,c);
}
}
int main()
{
int n;
cin>>n;
h(n,'a','b','c');
return 0;
}
1.2 平面上的直线 Lines In The Plane
问题描述:平面上n条直线最多能把一个平面界定成多少个区域()?
要的到最多的区域就不能让任意3及以上条直线相交于同一个的店,所以每次添加一条直线(第i条)会在原来的基础上(不会减少原来的区域数量)都与其他直线相交(不交于交点)会产生i个区域。
所以,
在加大一点难度,把直线换成折线,最多可以得到几个区域呢()?
一条折线可以表示为两条直线相交并去除了从交点开始的一端(看虚线),所以在直线的基础之下,每多一条折线就会少两个区域。
所以;