宁波工程学院 1350 气坏了老虎乐坏了兔 记忆化搜索 帅呆了

来源:互联网 发布:学it 编辑:程序博客网 时间:2024/04/30 04:51
  • http://ac.nbutoj.com/Problem/view.xhtml?id=1350

  • [1350] 气坏了老虎乐坏了兔

  • 时间限制: 2000 ms 内存限制: 65535 K
  • 问题描述
  • 这天小灰兔又把老虎给气坏了,于是就偷着乐呢。
    小灰兔欢乐的时候就爱弹琴。所谓的琴不是一般的琴,而且很大,弹琴的时候,小灰兔需要站在各个琴键上跳动到另一个琴键。
    所有琴键放在一个N * N的琴架上,一共N行琴键,每行N个琴键。
    小灰兔只能从一个琴键跳到周围共享一边的四个琴键上。
    问小灰兔如果从任意一个琴键开始弹一首需要跳M格琴键的曲子的话,有多少不同的曲子可以弹?
  • 输入
  • 本题有多组数据,每组数据第一行为两个整数N和M(2 <= N <= 100, 1 <= M <= 500)。
  • 输出
  • 对于每组数据,输出不同的曲子数。(所有答案对1000000007取余)
  • 样例输入
  • 2 12 2
  • 样例输出
  • 48
  • 提示
  • 来源
  • XadillaX

    参考了大神的代码才搞定          居然才明白这就是记忆化搜索 

    解题思路:用mat[k][i][j]记录弹了k个健后,停在了i行j列的位置上的弹法数,
     * 那么状态转移方程就是mat[k][i][j]=sum{mat[k-1][a][b]}(a,b)为靠近(i,j)的
     * 四个位置,最后的答案就是sum{ mat[m][i][j] }(1<=i<=n,1<=j<=n)
    #include<stdio.h>#include<string.h>const int mod=1000000007;int n,m,a[2][150][150],step[4][2]={0,1,0,-1,1,0,-1,0};int main(){int i,j,x,y;while(scanf("%d %d",&n,&m)!=EOF){memset(a,0,sizeof(a));for(i=1;i<=n;i++)for(j=1;j<=n;j++)a[0][i][j]=1;m--;for(int t=1;t<=m;t++){for(i=1;i<=n;i++)for(j=1;j<=n;j++)for(int k=0;k<4;k++){x=step[k][0]+i;y=step[k][1]+j;if(x>=1&&x<=n&&y>=1&&y<=n)                                a[1][i][j]=(a[1][i][j]+a[0][x][y])%mod;         }for(i=1;i<=n;i++)for(j=1;j<=n;j++){a[0][i][j]=a[1][i][j];a[1][i][j]=0;}}int ans=0;for(i=1;i<=n;i++)for(j=1;j<=n;j++)ans=(ans+a[0][i][j])%mod;printf("%d\n",ans);}return 0;}
     
     
    记忆化搜索:算法上依然是搜索的流程,但是搜索到的一些解用动态规划的那种思想和模式作一些保存。
    一般说来,动态规划总要遍历所有的状态,而搜索可以排除一些无效状态。
    更重要的是搜索还可以剪枝,可能剪去大量不必要的状态,因此在空间开销上往往比动态规划要低很多。
    记忆化算法在求解的时候还是按着自顶向下的顺序,但是每求解一个状态,就将它的解保存下来,
    以后再次遇到这个状态的时候,就不必重新求解了。
    这种方法综合了搜索和动态规划两方面的优点,因而还是很有实用价值的。
  • 原创粉丝点击