看到网上解法太多,感觉有点乱,其实就是水dp一枚,搞清递推过程就行了;
dp【i】【j】【k】k=0表示到达(i,j)这个点最多的完全消耗能量,k1小时种数,其中(i,j)这些点不是全部点,而是到达这个点能量正好为0的点或中点;
leap【】【】用来标记这些点,在跑的过程中就只跑这些点;
递推公式为
if(dp[i][j][0]+1==dp[x][y][0]) dp[x][y][1]+=dp[i][j][1];
else if(dp[i][j][0]+1>dp[x][y][0])
{
dp[x][y][0]=dp[i][j][0]+1;
dp[x][y][1]=dp[i][j][1];
}
对中点要特判下就行;
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } int n,m; int judge(int x,int y) { if(x>n||y>m) return 0; return 1; } int main() { int i,j,T; int map[110][110],leap[110][110]; int dp[110][110][2]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) scanf("%d",&map[i][j]); } memset(dp,0,sizeof(dp)); memset(leap,-1,sizeof(leap)); dp[1][1][0]=0; dp[1][1][1]=1; leap[1][1]=0; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { if(map[i][j]==0) continue; if(leap[i][j]>=0) { int t=map[i][j]; //printf("$$$%d\n",t); if(n-i+m-j<t) { if(dp[i][j][0]==dp[n][m][0]) dp[n][m][1]+=dp[i][j][1]; else if(dp[i][j][0]>dp[n][m][0]) { dp[n][m][0]=dp[i][j][0]; dp[n][m][1]=dp[i][j][1]; } } else if(n-i+m-j==t) { if(dp[i][j][0]+1==dp[n][m][0]) dp[n][m][1]+=dp[i][j][1]; else if(dp[i][j][0]+1>dp[n][m][0]) { dp[n][m][0]=dp[i][j][0]+1; dp[n][m][1]=dp[i][j][1]; } } else { for(int k=0;k<=t;k++) { int x=i+k; int y=j+t-k; if(!judge(x,y)) continue; leap[x][y]=1; if(dp[i][j][0]+1==dp[x][y][0]) dp[x][y][1]+=dp[i][j][1]; else if(dp[i][j][0]+1>dp[x][y][0]) { dp[x][y][0]=dp[i][j][0]+1; dp[x][y][1]=dp[i][j][1]; } } } } } printf("%d %d\n",dp[n][m][0],dp[n][m][1]); } return 0; }
时间: 2024-11-17 02:25:28