最近乎乎刚从网上买回来一盒水彩笔,奇怪的是这盒水彩笔只有红色、粉色和绿色,而且数量也非常多,总和n(0<n<=50)。乎乎很郁闷,想着要去找卖家退货,这时乎乎突然想起来的前几天算法书上的一道题,正好可以拿水笔模拟一下。题目如下:有排成一行的n个方格,用红、粉、绿三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色。求全部的满足要求的图法。学长顿时很高兴,拿起水彩笔就开始模拟。
主要思路是递推,要注意f[N]设置的意思是合法的选择数,转移方程可以由,第n格的合法数可以由n-1格子不同和相同推断。其中当n-1个格子和第一个格子相同的时候,这是不合法的选择数,所以没有存储在我们的f[n-1]中,但是我们可以通过n-2的合法解推导出n-1和第一格相同的个数,就是所有n-2和第一个格子不相同个数(我们的合法解也就是f[n-2])选择和第一个格子一样的颜色,得到n-1格子相同的个数(f[n-2]*1),此时推到n使有两种选择所以为(f[n-2]*1*2)。其次,当n-1个格子和第一个格子不同时(我们的合法解f[n-1]),此时可以推导n个格子有唯一选择和第一个格子一个颜色。故转移方程:f[i]=f[i-1]*1+f[i-2]*2。
最重要的状态转移方程已经出来了,剩下的只需要确定我们递推的边界。第一格有三种选择,第二格和第一个不冲突一共6种选择,第三格并不满足我们的转移方程,因为第二格不存在和第一个相同的颜色的可能,所以转移方程会多考虑相同的可能性,多算个3*2,所以三格也要确定边界为6.
#include<bits/stdc++.h>
using namespace std;
const int N=55;
long long f[N];
int main()
{
int n;
cin >> n;
f[1]=3;
f[2]=6;
f[3]=6;
for(int i=4;i<=n;i++)
{
f[i]=f[i-1]+2*f[i-2];
}
cout << f[n];
return 0;
}