How many ways
HDU - 1978题意:n*m的棋盘, 机器人由左上角走到右下角, 规则如下:
1.机器人一开始在棋盘的起始点并有起始点所标有的能量。
2.机器人只能向右或者向下走,并且每走一步消耗一单位能量。
3.机器人不能在原地停留。
4.当机器人选择了一条可行路径后,当他走到这条路径的终点时,他将只有终点所标记的能量。
两个方法, 本质一样, 写法不同;
1.动态规划;左上角为1;每次找能走到的, 累加, 输出右下角;
#include <cstdio>
#include <cstring>
int a[110][110], dp[110][110];
int main(){
int T;
scanf("%d", &T);
while(T--){
int n, m;
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
scanf("%d", &a[i][j]);
}
}
memset(dp, 0, sizeof(dp));
dp[0][0]=1;
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
if(dp[i][j]){
int t=a[i][j];
for(int x=0; x<=t; x++){
for(int y=0; y<=t; y++){
if(x+y==0) continue;
if(x+y>t) break;
int tx, ty;
tx=x+i;
ty=y+j;
if(tx>=n||ty>=m) continue;
dp[tx][ty]+=dp[i][j];
dp[tx][ty]%=10000;
}
}
}
}
}
printf("%d\n", dp[n-1][m-1]%10000);
}
return 0;
}
2.记忆化搜索,初始化全为-1, 右下角为1, 由左上角开始, 搜到不为-1的就return;
并在过程中改写mark;
#include <cstdio>
#include <cstring>
int a[110][110], mark[110][110];
int n, m;
int dfs(int x, int y){
if(mark[x][y]!=-1) return mark[x][y];
int t, x1, y1;
int temp=0;
t=a[x][y];
for(x1=0; x1<=t; x1++){
if(x+x1>=n) break;
for(y1=0; y1<=t; y1++){
if(y1+y>=m) break;
if(x1+y1>t) break;
if(x1+y1==0) continue;
temp+=dfs(x1+x, y1+y);
}
}
temp%=10000;
return mark[x][y]=temp;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++){
for(int j=0; j<m; j++){
scanf("%d", &a[i][j]);
mark[i][j]=-1;
}
}
mark[n-1][m-1]=1;
printf("%d\n", dfs(0, 0));
}
return 0;
}