题目内容:
对于Hanoi塔问题,如果要移动n个盘子,假设一秒钟移动1000次,求出完成移动大约需要几年几月几日。按照一年365天,一个月30天来算即可。不足1日的,按1日来算。
输入格式:
正整数n,n不超过64
输出格式:
a b c,其中a代表年,b代表月,c代表日,按照一年365天,一个月30天来算即可。注意行末不要有多余空格。
输入样例1:
1
输出样例1:
0 0 1
输入样例2:
36
输出样例2:
2 2 6
时间限制:1000ms内存限制:65536kb
汉诺塔是我一直没搞懂的问题,但这题似乎与汉诺塔本身没啥关系,只是要用到总共要移动(2^n-1)次的结论。
一开始,我没有多想,思路就是简单粗暴,如下
#include<iostream>
using namespace std;
void f(unsigned long long sum)
{
if(sum%(1000*60*60*24)!=0)
sum=sum/1000/60/60/24+1;
else
sum=sum/1000/60/60/24;
int a,b,c;
for(a=0;;a++)
{
for(b=0;b<=12;b++)
{
for(c=0;c<=29;c++)
{
if(365*a+30*b+c==sum)
cout<<a<<' '<<b<<' '<<c;
}
}
}
}
int main()
{
int n,i;
cin >> n;
unsigned long long sum=1;
for(i=1;i<=n;i++)
sum*=2;
if (n <= 64)
f(sum-1);
}
可以说,主打的就是粗暴,毫无技术含量,运行时间贼长,一点都不优雅,自然是不行的。
因此,稍微做了下改动,如下
#include<iostream>
using namespace std;
void f(unsigned long long sum)
{
long long v=60*60*24;
double a;
a=sum/(1000*v*365);//年份
if(a>=1)
cout<<(int)a<<' ';
else
cout<<0<<' ';
sum-=(int)a*v*365*1000;
double b;
b=sum/(1000*v*30);//月份
if(b>=1)
cout<<(int)b<<' ';
else
cout<<"0 ";
sum-=(int)b*v*30*1000;
double c;
c=sum/(1000*v);//日
if(c>=1)
cout<<((int)c+1);
else
cout<<1;
}
int main()
{
int n,i;
cin >> n;
unsigned long long sum=1;
for(i=1;i<=n;i++)
sum*=2;
if (n <= 64)
f(sum-1);
}
运行后,结果是对的,运行时间也短了不少,思路依然简单粗暴,但是稍微优化了一点。
接下来的这个思路,应该是最优雅的,如下
#include<iostream>
using namespace std;
int main()
{
unsigned long long year,month,day,second=1;
int i,n,v=1000*60*60*24;
cin>>n;
for(int i=1;i<=n;i++)
second*=2;
second-=1;
if(second%v==0)
day=second/v;
else
day=second/v+1;
year=day/365;
day=day%365;
month=day/30;
day=day%30;
cout<<year<<' '<<month<<' '<<day;
}
感谢阅读,希望大佬可以提供更加优雅的代码!