2019.6.4 HDOJ-20XX递推求解专题练习

最近好慌啊
东北赛打铁了,虽说是意料之内,但还是好气啊

题目地址

递推求解专题练习(For Beginner)

AC的代码

2044 一只小蜜蜂…

/*HDOJ2044 有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房,不能反向爬行。请编程计算蜜蜂从蜂房a爬到蜂房b的可能路线数。
其中,蜂房的结构如下所示。*/
#include<stdio.h>
long long fun(long long x);
long long arr[60]={1,1};
int main(void)
{
	int n;
	long long a,b;
	scanf("%d",&n);
	while(n-->0){
		scanf("%lld %lld",&a,&b);
		printf("%lld\n",fun(b-a));
	}
	return 0;
}
long long fun(long long x)//记忆化递归写法 
{
	if(x==1)
		return arr[x];
	else if(x==0)
		return arr[x];//从x到x也是一种走法 
	if(arr[x]!=0)
		return arr[x];
	else
		return arr[x]=fun(x-1)+fun(x-2);
}

又见斐波那契数列

2045 不容易系列之(3)—— LELE的RPG难题

//有些类似圆排列,但是有确定起点
//考虑当前格子时,一定不会与1相同。但是考虑下一个格子时,要额外考虑上一个格子与第一个相同的情况
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    long long arr[55]={0,3,6,6};
    int i;
    for(i=4;i<52;i++){//涂第n个格子时,n-1有两种情况:与1相同或不同。
            //不同的话,只能填剩下的一种。这部分=F(n-1)。
            //1与n-1相同的话,可以填与1不同的两种,对应情况F(n-2)*2
        arr[i]=arr[i-1]+arr[i-2]*2;
    }
    int n;
    while(cin>>n)
        cout<<arr[n]<<endl;
    return 0;
}

考虑当前格子时,一定不会与1相同。但是考虑下一个格子时,要额外考虑上一个格子与第一个相同的情况。
涂第n个格子时,n-1有两种情况:与1相同或不同。
①不同的话,只能填剩下的一种。这部分=F(n-1)。
②1与n-1相同的话,可以填与1不同的两种,对应情况F(n-2)*2。
递推公式:F(n)=F(n-1)+F(n-2)*2

2046 骨牌铺方格

#include<iostream>
using namespace std;
int main()
{
    long long arr[55]={0,1,2,3},i;
    for(i=4;i<55;i++)
        arr[i]=arr[i-1]+arr[i-2];
    int n;
    while(cin>>n)
        cout<<arr[n]<<endl;
    return 0;
}

这个很容易看出来……

2047 阿牛的EOF牛肉串

//HDOJ-2047阿牛的EOF牛肉串
//递推,三个字符,第n位与第n-1位是不是O有关
//假如n为O,n-1一定不为O,n-2任意,n-1为E或F,这部分为F(n-2)*2
//假如n不为O,n-1可以随便取,n为E或F,F(n-1)*2
#include<iostream>
using namespace std;
int main()
{
    long long arr[45]={0,3,8},i;
    for(i=3;i<45;i++)
        arr[i]=2*arr[i-1]+2*arr[i-2];
    int n;
    while(cin>>n)
        cout<<arr[n]<<endl;
    return 0;
}

三个字符,第n位与第n-1位是不是O有关
①假如n为O,n-1一定不为O,n-2任意,n-1为E或F,这部分为F(n-2)*2
②假如n不为O,n-1可以随便取,n为E或F,F(n-1)*2
递推公式:F(n)=F(n-2)*2+F(n-1)*2

2048 神、上帝以及老天爷

//设第n项错排数为F(n),则n-1项为F(n-1)
//1.将第n个元素放在其他位置,一共有n-1种,假设放在第k个位置
//2.放置第k个元素,有两种可能:
//①k放在第n个位置,n放在k的位置,剩下n-2个元素错排,一共F(n-1)种可能
//②k不放在第n个位置,n-1个元素错排,一共F(n-2)种可能
//递推公式F(n)=(n-1)*[F(n-2)+F(n-1)]
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
	long long F[30]={0,0,1},all=2;//all是所有组合的可能个数
	double rate[30]={0,0,0.5};
	int i,t;
	for(i=3;i<22;i++){
		F[i]=(i-1)*(F[i-2]+F[i-1]);
		all*=i;
		rate[i]=(double)F[i]/all;
	}
	int c;
	cin>>c;
	while(c--){
		cin>>t;
		printf("%.2lf%%\n",rate[t]*100);
	}

	return 0;
}

全错位排列
设第n项错排数为F(n),则n-1项为F(n-1)
1.将第n个元素放在其他位置,一共有n-1种,假设放在第k个位置
2.放置第k个元素,有两种可能:
①k放在第n个位置,n放在k的位置,剩下n-2个元素错排,一共F(n-1)种可能
②k不放在第n个位置,n-1个元素错排,一共F(n-2)种可能
递推公式F(n)=(n-1)*[F(n-2)+F(n-1)]

2049 不容易系列之(4)——考新郎

//错排,2048进阶
//一共有N对,选出M对进行错排,一共有C(N,M)种选法
//用错排的递推公式F(n)=(n-1)*[F(n-2)+F(n-1)]乘以组合数即为答案
#include<iostream>
#include<cstdio>
using namespace std;
long long fun(long long n,long long m);
int main()
{
	long long F[25]={0,0,1},i;
	for(i=3;i<22;i++){
		F[i]=(i-1)*(F[i-2]+F[i-1]);
	}
	int C,n,m;
	cin>>C;
	while(C--){
		cin>>n>>m;
		cout<<fun(n,m)*F[m]<<endl;
	}
	return 0;
}
long long fun(long long n,long long m)
{
	long long a=1,b=1,c=1,i;
	for(i=1;i<=n;i++){
		a*=i;
	}
	for(i=1;i<=m;i++){
		b*=i;
	}
	for(i=1;i<=n-m;i++){
		c*=i;
	}
	return a/(b*c);
}

错排,2048进阶
一共有N对,选出M对进行错排,一共有C(N,M)种选法。
用错排的递推公式F(n)=(n-1)*[F(n-2)+F(n-1)]乘以组合数即为答案。

2050 折线分割平面

//将当前加入折线看成两段,每段都与之前折线的两边有2*(n-1)个交点,每边产生2n-3个线段,1条射线,1个折角的一边
//一个射线或线段产生一个新区域,折角算一个新区域,两条共产生4n-3个新区域
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    int c,i,TAT[10005]={0,2,7};
    for(i=3;i<10003;i++)
        TAT[i]=TAT[i-1]+(i-1)*4+1;
    cin>>c;
    while(c--){
        int n;
        cin>>n;
        cout<<TAT[n]<<endl;
    }
//    for(i=4;i<10003;i++)
//        cout<<TAT[i]<<endl;
    return 0;
}

将当前加入折线看成两段,每段都与之前折线的两边有2*(n-1)个交点,每边产生2n-3个线段,1条射线,1个折角的一边。
一个射线或线段产生一个新区域,折角算一个新区域,两条共产生4n-3个新区域

HDOJ2064汉诺塔III(递推)

Problem Description
约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。
Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?

Input
包含多组数据,每次输入一个N值(1<=N=35)。

Output
对于每组数据,输出移动最小的次数。

Sample Input
1
3
12

Sample Output
2
26
531440

#include<iostream>
using namespace std;
int main(void)
{
	long long st[40]={0,2,8},i,n;
	for(i=3;i<37;i++){
		st[i]=3*st[i-1]+2;
	}
	while(cin>>n)
		cout<<st[n]<<endl;
	return 0;
}
//woc,这题我居然独立做出来了
//一共n层,先将上面n-1层移到㈢柱,再将第n层移至㈡柱
//再将㈢柱的n-1层移到㈠柱,再将㈡柱的第n层移至㈢柱,㈠柱的n-1层也移至㈢柱
//递推公式st[i]=3*st[i-1]+2;
//好吧,确实不难(っ °Д °;)っ

汉诺塔IV

#include<iostream>
using namespace std;
typedef long long ll;
ll F1[30]={0,1,4},F2[30]={0,2,4};//F1为将上n-1移到相邻柱子上所需步数(下标代表移动数量),F2为整个移到最右边所需步数
//通项公式:①F2[n]=2F1[n-1]+2,②F1[n]=3F1[n-1]+1
int main()
{
	int i,n,t;
	for(i=3;i<=21;i++)
		F1[i]=3*F1[i-1]+1;
	for(i=3;i<=21;i++)
		F2[i]=2*F1[i-1]+2;
	cin>>t;
	while(t--){
		cin>>n;
		cout<<F2[n]<<endl;
	}
	return 0;
}

分析:和上面那题结合来看,加入了新规则:允许最大的放在最上面
第一部分:
步骤一:将上面n-1个移到Ⅱ柱
步骤二:将Ⅰ柱剩下的第n片移到Ⅲ柱(这部分需要2步)
步骤三:将Ⅱ上的n-1个移到Ⅲ柱
①递推公式:F2[n]=2F1[n-1]+2
可以看出来,第一部分步骤一和步骤三消耗步数一样。
但是移动上面n-1层时不可以将最大的放在最上面
这时求解移动上面n-1层就变成了汉诺塔Ⅲ将整体移动到相邻柱子上的情况。
第二部分:分析上面n-1层移到相邻柱子所需步数
(不管n-1层在中间还是两边,步数都是一样的,以Ⅰ移到Ⅱ为例)
步骤一:将上面n-1个移到Ⅲ柱,共2F1[n-1]步
步骤二:将Ⅰ柱剩下的第n片移到Ⅱ柱(1步)
步骤三:将Ⅲ上的n-1个移到Ⅱ柱,F1[n-1]步
这部分的递推公式②F1[n]=3F1[n-1]+1
合起来就是F2[n]=6F1[n-2]+4

Run ID Submit Time Judge Status Pro.ID Exe.Time Exe.Memory Code Len. Language Author
29471468 2019-06-23 14:01:07 Accepted 2077 31MS 1800K 420 B C++ Overstars
29447707 2019-06-17 00:00:39 Accepted 2064 31MS 1800K 191 B C++ Overstars
29383967 2019-06-04 15:55:12 Accepted 2049 31MS 1792K 628 B C++ Overstars
29381358 2019-06-03 22:45:28 Accepted 2048 0MS 1796K 667 B C++ Overstars
29324683 2019-05-27 19:40:39 Accepted 2050 0MS 1832K 529 B C++ Overstars
29316064 2019-05-26 15:15:43 Accepted 2047 0MS 1796K 416 B C++ Overstars
29314735 2019-05-26 12:40:02 Accepted 2046 0MS 1800K 229 B C++ Overstars
29314669 2019-05-26 12:22:57 Accepted 2045 15MS 1800K 573 B C++ Overstars
28760028 2019-03-31 08:57:52 Accepted 2044 0MS 1696K 420 B C Overstars

2019年6月4日16点20分

2019年6月23日14点38分 加了两道汉诺塔的题

发布了71 篇原创文章 · 获赞 12 · 访问量 7553

猜你喜欢

转载自blog.csdn.net/Miaplacidus/article/details/90770688