小W走迷宫

来源:互联网 发布:t95e6最新版本数据 编辑:程序博客网 时间:2024/05/02 18:08
小W 走迷宫
【问题描述】
小W 被小M 困在了一个方格矩阵迷宫里,矩阵边界在无穷远处,我们做出如下的
假设:
a. 每走一步时,只能从当前方格移动一格,走到某个相邻的方格上;
b. 走过的格子立即塌陷无法再走第二次;
c. 只能向北、东、西三个方向走。
小W 走了没多久就累坏了,他很想知道如果允许在方格矩阵上走 N 步,共有多少
种不同的方案。( 开始时小W 就在方格矩阵上的任意位置,2 种走法只要有一步不一样,
即被认为是不同的方案)
【输入格式】
一行输入N。
【输出格式】

一行输出方案个数。

/*可以发现由于只有三个方向且不能回头,所以和位置并没有任何关系,那么就只和剩下的step和到达方向有关系,所以用num【i】【j】表示还剩下j步,且通过i方向到达当前这一步。这样的时间复杂度是O(n*3)的;注意题目需要用高精度!!! */#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#define N 10000using namespace std;int n;bool vis[N][4];int num[N][4][N],ans[N],as,tmp[N],len,nxt;void dfs(int frm,int cal_dep){if(!cal_dep){vis[cal_dep][frm]=1;num[cal_dep][frm][1]=1;num[cal_dep][frm][0]=1;int x=1;while(x<=as && ans[x]==9) x++;as=max(as,x);ans[x]++;for(int i=1;i<x;i++) ans[i]=0;return ;}for(int i=1;i<=3;i++){if(i==(4-frm) && frm!=2) continue;if(!vis[cal_dep-1][i]) dfs(i,cal_dep-1);else //ans+=num[cal_dep-1][i];{len=1;nxt=0;while(len<=as || len<=num[cal_dep-1][i][0]){tmp[len]=(ans[len]+num[cal_dep-1][i][len]+nxt)%10;nxt=(ans[len]+num[cal_dep-1][i][len]+nxt)/10;len++;}if(nxt) tmp[len]=nxt;else len--;for(int j=1;j<=len;j++) ans[j]=tmp[j];as=len;}len=1;nxt=0;while(len<=num[cal_dep][frm][0] || len<=num[cal_dep-1][i][0]){tmp[len]=(nxt+num[cal_dep][frm][len]+num[cal_dep-1][i][len])%10;nxt=(nxt+num[cal_dep][frm][len]+num[cal_dep-1][i][len])/10;len++;}if(nxt) tmp[len]=nxt;else len--;for(int j=1;j<=len;j++) num[cal_dep][frm][j]=tmp[j];num[cal_dep][frm][0]=len;}vis[cal_dep][frm]=1;}int main(){//freopen("game.in","r",stdin);//freopen("game.out","w",stdout);scanf("%d",&n);for(int i=1;i<=3;i++) dfs(i,n-1);for(int i=as;i;i--) printf("%d",ans[i]);return 0;}/*当然还有第二种方法:a[i] 记录走第i步是往北走的个数,b[i] 记录走第i步是往东或者者西时候的个数,c[i]=a[i]+b[i]。有以下递推式:a[i]=a[i-1]+b[i-1]=c[i-1]b[i]=2*a[i-1]+b[i-1]//如果上一步是向上走的那么当前这一步可以向东也可以向西,所以要乘2,但上一步是向东或向西,这不能反走,自能乘1 则 c[i]=a[i]+b[i]=3*a[i-1]+2*b[i-1]=2c[i-1]+a[i-1]=2c[i-1]+c[i-2]。直接高精度。*/#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#define N 300000using namespace std;int n,nxt=0,len,lena,lenb,as;int a[N],b[N],ans[N];void cal(){nxt=0;len=1;while(len<=lenb){int tmp=b[len]*2+nxt;ans[len]=(tmp)%10;nxt=tmp/10;len++;}if(nxt) ans[len]=nxt;else len--;as=len;}void del(){nxt=0;len=1;while(len<=lena || len<=as){int tmp=a[len]+ans[len]+nxt;ans[len]=tmp%10;nxt=tmp/10;len++;}if(nxt) ans[len]=nxt;else len--;as=len;for(int i=1;i<=lenb;i++) a[i]=b[i];lena=lenb;for(int i=1;i<=as;i++) b[i]=ans[i];lenb=as;}int main(){freopen("game.in","r",stdin);freopen("game.out","w",stdout);scanf("%d",&n);if(n<=2){printf("%d",(n==1?3:7));return 0 ;}a[1]=3;b[1]=7;lena=1;lenb=1;for(int i=3;i<=n;i++){cal();del();}for(int i=as;i;i--) printf("%d",ans[i]);return 0; }