题目:http://acm.hdu.edu.cn/showproblem.php?pid=1978
第一次接触记忆化搜索+DP..
题目中“他将只有终点所标记的能量”是解题的关键啊!一开始还老想剩余能量怎么处理.....悲剧。
这题可以分为两种DP方式,一种是当前的这个点可以到达其他点的方法数和能到达当前点的方法数。。
两种状态转移方程也差不多。
下面分别是两种方法的AC代码
第一种:
#include<iostream>
using namespace std;
int dp[201][201];
int map[201][201];
int n,m;
int min(int a,int b){ return a>b?b:a;}
int dfs(int x,int y,int k)
{
int i,j;
if(x==n&&y==m)
return 1;
if(dp[x][y]!=0)
return dp[x][y];
for(i=0;i<=min(k,n-x);i++)
for(j=0;j<=min(k-i,m-y);j++)
{
if(i==0&&j==0) continue ;
dp[x][y]+=dfs(x+i,y+j,map[x+i][y+j]);
dp[x][y]%=10000;
}
return dp[x][y];
}
int main()
{
int t,i,j;
cin>>t;
while(t--)
{
cin>>n>>m;
memset(dp,0,sizeof(dp));
memset(map,0,sizeof(map));
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
cin>>map[i][j];
dfs(1,1,map[1][1]);
printf("%d\n",dp[1][1]);
}
return 0;
}
第二种:
#include<iostream>
using namespace std;
int dp [201][201];
int main()
{
int n,m;
int t,i,j,k,l;
int num;
cin>>t;
while(t--)
{
cin>>n>>m;
memset(dp,0,sizeof(dp));
dp[0][0]=1;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
{
// scanf("%d",&num);
cin>>num;
for(k=0;k<=num;k++)
for(l=0;l+k<=num;l++)
{
if(k==0&&l==0)
continue;
dp[i+k][j+l]=(dp[i+k][j+l]+dp[i][j])%10000;
}
}
printf("%d\n",dp[n-1][m-1]);
}
return 0;
}