hdu 1978 How many ways 记忆化搜索+DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1978
思路很好想;
定义f[i][j]表示从点(i,j)出发到达(n,m)的方法数;
那么对于一切从(i,j)可以到达的点来说,f[i][j]+=∑f[k][p];其中(k.p)表示(i,j)可以到达的点,应该比较好理解的吧;
最后可以通过DFS 求解每一个点到达(n,m)的方案数,答案就为f[1][1];
注意的一点是:
在DFS过程中要保留答案状态,避免重复计算。即所谓的记忆化。
代码如下:
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 #define MAX 110 7 #define MOD 10000 8 int n,m; 9 int map[MAX][MAX]; 10 int ans; 11 int f[MAX][MAX]; 12 int dfs(int x,int y) 13 { 14 if(x==n&&y==m) {f[n][m]=1;return 1;} 15 int power=map[x][y]; 16 if(power==0) return -1; 17 for(int i=x;i<=x+power;i++) 18 for(int j=y;j<=y+power-(i-x);j++) 19 { 20 21 if(i==x&&j==y) continue; 22 if(i>n||i<0||j>m||j<0) continue; 23 if(f[i][j]==0) 24 { 25 f[i][j]=dfs(i,j); 26 } 27 if(f[i][j]>0) {f[x][y]+=f[i][j];f[x][y]=f[x][y]%MOD;} 28 if(f[i][j]==-1) continue; 29 } 30 return f[x][y]; 31 } 32 int main() 33 { 34 int t; 35 scanf("%d",&t); 36 while(t--) 37 { 38 memset(f,0,sizeof(f)); 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=n;i++) 41 for(int j=1;j<=m;j++) 42 scanf("%d",&map[i][j]); 43 dfs(1,1); 44 cout<<f[1][1]<<endl; 45 } 46 return 0; 47 }