這是一個簡單的生存遊戲,你控制一個機器人從一個棋盤的起始點(1,1)走到棋盤的終點(n,m)。遊戲的規則描述如下:
1.機器人一開始在棋盤的起始點并有起始點所标有的能量。
2.機器人隻能向右或者向下走,并且每走一步消耗一機關能量。
3.機器人不能在原地停留。
4.當機器人選擇了一條可行路徑後,當他走到這條路徑的終點時,他将隻有終點所标記的能量。
![]()
How many ways 如上圖,機器人一開始在(1,1)點,并擁有4機關能量,藍色方塊表示他所能到達的點,如果他在這次路徑選擇中選擇的終點是(2,4) 點,當他到達(2,4)點時将擁有1機關的能量,并開始下一次路徑選擇,直到到達(6,6)點。
我們的問題是機器人有多少種方式從起點走到終點。這可能是一個很大的數,輸出的結果對10000取模。
Input
第一行輸入一個整數T,表示資料的組數。
對于每一組資料第一行輸入兩個整數n,m(1 <= n,m <= 100)。表示棋盤的大小。接下來輸入n行,每行m個整數e(0 <= e < 20)。
Output
對于每一組資料輸出方式總數對10000取模的結果.
Sample Input
1
6 6
4 5 6 6 4 3
2 2 3 1 7 2
1 1 4 6 2 7
5 8 4 3 9 5
7 6 6 2 1 5
3 1 1 3 7 2
Sample Output
3948
題目分析:
這是一道記憶化搜尋的題目。
- 狀态表示:
f[x][y] //表示以(x,y)為起點,走到終點(n,m)有多少種走法
- 狀态計算:我們可以用dfs來周遊所有路徑,同時用上記憶化搜尋來避免重複計算。
ac代碼:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
#include <iomanip>
#define LL long long
using namespace std;
const int N=105,mod=10000;
int n,m;
int a[N][N],f[N][N];
int dfs(int x,int y)
{
if(f[x][y]!=-1) return f[x][y]; //記憶化,如果f[x][y]已經被計算過了
f[x][y]=0; //那麼跳過計算
for(int i=0;i<=a[x][y];i++) //周遊目前點(x,y)的能量所能到達的
for(int j=0;j<=a[x][y]-i;j++) //所有點
{
if(x+i>=1&&x+i<=n&&y+j>=1&&y+j<=m) //保證(x+i,y+j)沒有越界
f[x][y]=(f[x][y]+dfs(x+i,y+j))%mod;//遞歸求解
}
return f[x][y];
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
memset(f,-1,sizeof f); //初始化
f[n][m]=1;
dfs(1,1);
cout<<f[1][1]<<endl; //f[1][1]即為正确答案
}
return 0;
}