有排成一行的n个方格,用红(Red)、粉(Pink)、绿(Green)三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色.求全部的满足要求的涂法.(n<=50);
(注:因为n=50的时候,假设最后一个方格可以涂与第一个相同的颜色,那么它总共的涂法为3*2*2.........(49个2);该数字范围已经远远超过(32位)int 型,所以要用(64位)long long;(long long 型的输出格式为"%I64d".
用三维数组,控制方格个数(n),首尾方格的颜色(0,1,2),存放该情况时,总共的涂色方法。
第一个方格有三种涂法,即a[1][0][0]=1;a[1][1][1]=1; a[1][2][2]=1;
对于n-1个方格,假设我们已经知晓给该方格填色的方法,那么再加上一个方格,先控制他最后一个方格的颜色与倒数第二个方格的颜色不相同,得到递推。
递推完后,再控制整个长度的方格首尾是否一致,将所有不一致的进行相加。六种情况((首,尾)(0,1),(0,2),(1,0),(1,2),(2,0),(2,1))
(注:因为n=50的时候,假设最后一个方格可以涂与第一个相同的颜色,那么它总共的涂法为3*2*2.........(49个2);该数字范围已经远远超过(32位)int 型,所以要用(64位)long long;(long long 型的输出格式为"%I64d".
用三维数组,控制方格个数(n),首尾方格的颜色(0,1,2),存放该情况时,总共的涂色方法。
第一个方格有三种涂法,即a[1][0][0]=1;a[1][1][1]=1; a[1][2][2]=1;
对于n-1个方格,假设我们已经知晓给该方格填色的方法,那么再加上一个方格,先控制他最后一个方格的颜色与倒数第二个方格的颜色不相同,得到递推。
递推完后,再控制整个长度的方格首尾是否一致,将所有不一致的进行相加。六种情况((首,尾)(0,1),(0,2),(1,0),(1,2),(2,0),(2,1))
在做题时,我总是忽略数的取值范围,在编完后也没有尝试取大一点的值,反思反思~~~
第二种方法,
第一个方格有三种涂法;N1=3;
第二个方格有6种涂法;N2=6;
第三个方格有六种涂法;N3=6;
在第n-1个方格的基础上加一个方格,原本第n-1个格子与第一个不同色,那么最后一个格子只有一种涂法。假如第n-1个格子与第一个格子同色,那么最后一个格子有两种涂法。所以,判断倒数n-2个格子,当只有(n-2)个格子的时候,第n-2个格子与第一个不同色,所以再加上两个格子的时候,若第n-1个格子于第一个格子颜色相同,那么最后一个格子有两种涂法。
所以N(n)=N(n-1)+2*N(n-2);
#include<stdio.h>
#include<string.h>
long long a[55][3][3];
int main( )
{
int n,i,j,k;
while (scanf("%d",&n)!=EOF)
{
memset(a,0,sizeof(a));
if(n==1)
{
printf("3\n");
continue;
}
a[1][0][0]=1;
a[1][1][1]=1;
a[1][2][2]=1;
for(i=2;i<=n;i++)
{
for(j=0;j<3;j++)
{
for(k=0;k<3;k++)
{
printf("a[%d][%d][%d]%I64d\n",i-1,j,k,a[i-1][j][k]);
for(int now=0;now<3;now++)
{
if(now!=k)
a[i][j][now]+=a[i-1][j][k];
}
}
}
}
long long h = 0;
for(j=0;j<3;j++)
{
for(k=0;k<3;k++)
{
if(j!=k)
h+=a[n][j][k];
}
}
printf("%I64d\n",h);
}
return 0;
}