How many ways

这个题的主要思路是DP

其实整体的思路——我为人人


 

设立f[i][j],即为从起点到第i行第j列位置的方案数

那么我们需要考虑:

当已经走到了i,j这个点,那么我将用这个格子的能量(num[i][j])。

因为方向是只能向右向下(不限定方向你还能求?),所以我们需要枚举新的点x,y。

这个点x,y是需要满足能够从i,j到达,没有越界,并且要看能量够不够让你走得到(不能让你走,你还能往下走?)或者是原地踏步

那么公式很显而易见了:f[x][y]=(f[x][y]+f[i][j])%10000; 即是把f[i][j]的方案数传递给f[x][y]。

以上就是一个点的“我为人人”策略,然后就继续跑下一个点,直到跑到最后一个点就停止。

初始值的话,就是起点赋值为1。


 

注意:f数组要清0,随时mod很香噢,多注意别越界,或者做了不该做的事情(类似原地踏步,你还在死命的算)


 

时间复杂度:

(1)首先,你需要枚举i,j。所以是这个地方是O(n2)

(2)其次,你还要在这个枚举里面再枚举一个点x,y,所以这个地方也是O(n2)(估大,实际远远小于这个数)

那么整个算法的时间复杂度即为O(n2)×O(n2)=O(n4),也就O(1004)=O(100,000,000)能过,当然也远远没有这么久


 

参考算法程序段(不要问我为什么不给全部程序,只是因为防止ctrl+c和ctrl+v而且给你主要程序段已经很香了

 1 f[1][1]=1;
 2 for(i=1;i<=n;i++)
 3 {
 4      for(j=1;j<=m;j++)
 5      {
 6          if(i==n&&j==m)continue;
 7          f[i][j]%=10000;
 8          for(x=i;x<=num[i][j]+i&&x<=n;x++)
 9               for(y=j;y<=num[i][j]+j&&y<=m;y++)
10               {
11                      if(x==i&&y==j)continue;
12                         if(num[i][j]>=x-i+y-j)
13                             f[x][y]=(f[x][y]+f[i][j])%10000; 
14                }
15      }
16 }
17 f[n][m]%=10000;
18 printf("%d\n",f[n][m]);    
View Code

 代码自行理解吧…… 其实花点时间,也是蛮好理解的

posted @ 2020-04-20 22:07  nhflsoiers  阅读(162)  评论(0)    收藏  举报