杭电oj——2045,2046,2047(递推)

Problem Description
人称“AC女之杀手”的超级偶像LELE最近忽然玩起了深沉,这可急坏了众多“Cole”(LELE的粉丝,即"可乐"),经过多方打探,某资深Cole终于知道了原因,原来,LELE最近研究起了著名的RPG难题:

有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色.求全部的满足要求的涂法.

以上就是著名的RPG难题.

如果你是Cole,我想你一定会想尽办法帮助LELE解决这个问题的;如果不是,看在众多漂亮的痛不欲生的Cole女的面子上,你也不会袖手旁观吧?

Input
输入数据包含多个测试实例,每个测试实例占一行,由一个整数N组成,(0

Output
对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。

Sample Input
1
2

Sample Output
3
6

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2045

分析

一看题目,就觉得简单啊,高中用排列组合公式就能做。但是好像笔试去算用公式就简单。换成代码就有点蒙。
参照了别人的思路,将这个问题分成两种情况去看,
考虑固定第n-1个格子(因为题目说首位不能同色,并且相邻不同色)分析n-1格子可以得出f(n)的规律

1.如果这个格子和第1个格子颜色不同,那么第n个格子只有1种选择,前n-1个格子的选择就是f(n-1),此时n个格子的选择是1*f(n-1)

  1. 如果这个格子和第1个格子颜色相同,那么第n个格子只有2种选择,前n-2个格子的选择就是f(n-2),此时n个格子的选择时2*f(n-2)

通过分析得出规律:f(n)=f(n-1)+2f(n-2)
注意:因为考虑的是第n-1个格子,上述情况第n-1格子分2种情况。
但是n必须从4开始推导,因为n=3时候,n-1必然和第一个格子不同所以就没有两种情况

参考(这个讲的更好):http://blog.sina.com.cn/s/blog_7865b0830101cf9f.html

摘自别人:http://zzp.me/2008-06-11/acm-hdu-2045/

杭电oj——2045,2046,2047(递推)_第1张图片
image.png

这就是用到了分析情况和递推的方法,这个思想还是要多加学习和提高


源代码

int main() {
    int n;
    long long a[51];
    a[1]=3;
    a[2]=6;
    a[3]=6;
    for(int i=4; i<=50; i++) {
        a[i]=a[i-1]+2*a[i-2];
    }
//直接算出来结果,后面直接打印出来就好
    while(scanf("%d",&n)!=EOF) {
        printf("%lld\n",a[n]);
    }
    return 0;
}

顺带一提:要定义long long 类型(long long int)数组不然,存进去会越界。n变大之后递归算出来的数字很大!
另外数组定义在函数外面比较好(这样可以定义大点)


Problem Description

在2×n的一个长方形方格中,用一个1× 2的骨牌铺满方格,输入n ,输出铺放方案的总数.
例如n=3时,为2× 3方格,骨牌的铺放方案有三种,如下图:


杭电oj——2045,2046,2047(递推)_第2张图片
oj2046

Input

输入数据由多行组成,每行包含一个整数n,表示该测试实例的长方形方格的规格是2×n (0

Output

对于每个测试实例,请输出铺放方案的总数,每个实例的输出占一行。

Sample Input

1
3
2

Sample Output

1
3
2

问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2046

分析

和上t思路一样,拿笔去算几个。因为牌子只可以竖着和横着,然后考虑第n-1和n-2情况。得出规律:f(n) = f(n-2) + f(n-1),n>2
这句话解释的很清楚:https://blog.csdn.net/tigerisland45/article/details/51852072

杭电oj——2045,2046,2047(递推)_第3张图片
image.png
int main()
{
    int n;
    long long a[51];
    a[0]=0;//没位置放牌子 
    a[1]=1;//2*1只够放一块 
    a[2]=2;//2*2 横着放两块或者竖着放两块 
    for(int i =3;i<=50;i++)
    {
        a[i]=a[i-2]+a[i-1];
    }
    while(~scanf("%d",&n))
    {
        printf("%lld\n",a[n]);
    }
    
 } 

oj2047阿牛的EOF牛肉串

Problem Description
今年的ACM暑期集训队一共有18人,分为6支队伍。其中有一个叫做EOF的队伍,由04级的阿牛、XC以及05级的COY组成。在共同的集训生活中,大家建立了深厚的友谊,阿牛准备做点什么来纪念这段激情燃烧的岁月,想了一想,阿牛从家里拿来了一块上等的牛肉干,准备在上面刻下一个长度为n的只由"E" "O" "F"三种字符组成的字符串(可以只有其中一种或两种字符,但绝对不能有其他字符),阿牛同时禁止在串中出现O相邻的情况,他认为,"OO"看起来就像发怒的眼睛,效果不好。

你,NEW ACMer,EOF的崇拜者,能帮阿牛算一下一共有多少种满足要求的不同的字符串吗?

PS: 阿牛还有一个小秘密,就是准备把这个刻有 EOF的牛肉干,作为神秘礼物献给杭电五十周年校庆,可以想象,当校长接过这块牛肉干的时候该有多高兴!这里,请允许我代表杭电的ACMer向阿牛表示感谢!

再次感谢!

Input
输入数据包含多个测试实例,每个测试实例占一行,由一个整数n组成,(0

Output
对于每个测试实例,请输出全部的满足要求的涂法,每个实例的输出占一行。

Sample Input
1
2

Sample Output
3
8

分析

一开始做就给坑到了,他问我有多少种不一样的,我直接用纸算,第一个格是3种情况,第二个格子由于不能出现相邻oo所以第二个格子2个选择,那3x2=6,一次类推第三格时候选择又变3种那总计3x2x3=18,我那个时候以为就是x2 和x3 的以此循环。结果发现错了,因为题目的那个是分前后顺序的排列,而我只是排列的不同没考虑前后比如题目答案EE算两种排列在我这种算法只算一种。看了讨论区代码,明悟了。还是要用递推,这次规律找了好久没找到。
后来参考:https://blog.csdn.net/lostaway/article/details/5742571

通过分析最后一个格子是不是o,将其分成两种情况是和否
1.如果是o,那么情况是:所以第n-1格子不能是o,所以n-1格子有两种选择,前面格子情况是f(n-2)种可能,那么乘上n-1的两种情况,再乘上最后格子的1种情况(最后一个格子是o)就变成所共有2* f(n-2)种可能
2.最后一个格子不是o,所以最后一个格子有两种选择,并且对n-1格子没限制。所以变成f(n-1)*2种可能

综合上述情况得出规律:f(n)=2*[f(n-1)+f(n-2)]


int main()
{
    int n;
    long long a[45];
    a[0]=0;
    a[1]=3;
    a[2]=8;
    for(int i=3;i<=40;i++)
    {
        a[i]=2*a[i-2]+2*a[i-1];
    }
    while(~scanf("%d",&n))
    {
        printf("%lld\n",a[n]);
    }
    return 0;
}

总结下

1.递推算法要多加学习(新增分析问题方法)
2.分析问题情况时候,考虑相互之间的影响
3.了解错排问题详情及其递推公式:
百度百科:https://baike.baidu.com/item/%E9%94%99%E6%8E%92%E5%85%AC%E5%BC%8F/10978508?fr=aladdin
大神详解:
https://www.luogu.org/blog/P6174/post-cuo-pai#

https://blog.csdn.net/bengshakalakaka/article/details/83420150

你可能感兴趣的:(杭电oj——2045,2046,2047(递推))