历届试题格子刷油漆
问题描述
X国的一段古城墙的顶端可以看成 2*N个格子组成的矩形(如下图所示),现需要把这些格子刷上保护漆。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
你可以从任意一个格子刷起,刷完一格,可以移动到和它相邻的格子(对角相邻也算数),但不能移动到较远的格子(因为油漆未干不能踩!)
比如:a d b c e f 就是合格的刷漆顺序。
c e f d a b 是另一种合适的方案。
当已知 N 时,求总的方案数。当N较大时,结果会迅速增大,请把结果对 1000000007 (十亿零七) 取模。
输入格式
输入数据为一个正整数(不大于1000)
输出格式
输出数据为一个正整数。
样例输入
2
样例输出
24
样例输入
3
样例输出
96
样例输入
22
样例输出
359635897
题中所提示的是动态规划
这个题就是先找规律分析,
当从角落开始时, 就三种情况 :
例如c[0][1]开始到c[1][1]结束,那么设从某一个角落开始到它邻近的角落结束 的个数是a[n],那么an=2*a[n-1],
从一个角落先经过邻近的角落在 经过剩下的 设从一个角落开始遍历的所有方法个数是 b[n],那么 这样的方式总共个数为2*b[n-1]
如果从一个角落开始,中间过程(除了第二个经过)经过它邻近的角落,那么肯定是第三个经过,(画图分析得出),那这种方式总共的个数是2*2*b[n-2]
sum=an+2*b[n-1]+2*2*b[n-2]
sum=4*sum (因为有四个角落)
然后再分析从中间开始的,设第i列 某一行的一个格子开始 肯定是先遍历左边再右边,或者先右边再左边,肯定还要经过这一列的另一行的这个格子,
所以先左边 看做是上面三种情况的第一种,右边是第二种 就是说 a[i]*2*b[n-i],先右边是第一种,左边是第二种 就是说a[n-i+1]*2*b[i-1]
每一列有两行,所以说是2 *(a[i]*2*b[n-i]+a[n-i+1]*2*b[i-1] )
对每一列遍历累加 最后加上角落的sum,就是最后结果
#include <iostream> #define MOD 1000000007 using namespace std; int long long a[1003],b[1003]; int main() { int n; long long int sum=0; cin>>n; if (n==1) { cout<<2; return 0; } a[1]=1; for (int i=2;i<=n;i++) a[i]=2*a[i-1]%MOD; b[1]=1;b[2]=6; for (int j=3;j<=n;j++) { b[j]=(a[j]+2*b[j-1]+4*b[j-2])%MOD; } sum=4*b[n]; for (int i=2;i<=n-1;i++) sum=(sum+2*(2*a[i-1]*2*b[n-i]%MOD+2*a[n-i]*2*b[i-1]%MOD)%MOD)%MOD; cout<<sum; }
下面是一开始我做的模拟一下线路(回溯递归) 虽然对,但是超时,n越大时间越长,不可取,
#include <iostream> using namespace std; bool a[2][1001]={0};int length=0,n;long long int count=0; void digui(int i,int j) { if(length>=2*n-1){count++; count%=1000000007; // cout<<endl; } else { for(int k=-1;k<=1;k++) for (int l=-1;l<=1;l++) if(i+k>=0&&i+k<=1&&j+l<=n&&j+l>=1) { if (a[i+k][j+l]==1) { a[i+k][j+l]=0; length++; //cout<<i+k<<" "<<j+l<<endl; digui(i+k,j+l); length--; a[i+k][j+l]=1; } } } } int main() { //输入一个正整数 cin>>n; for (int i=1;i<=n;i++) { a[0][i]=1; a[1][i]=1; } for (int i=0;i<2;i++ ) for (int j=1;j<=n;j++) { a[i][j]=0; digui(i,j); a[i][j]=1; } cout<<count; }