哈尔滨工程大学第十四届程序设计竞赛 (补题
F 小帆帆走迷宫(简单dp)
一道其实不是很难的四维dp 但是在考场上因为只记录转弯次数没记录方向没写出来
看题发现 其实这道题就是二维数塔+转向费的dp
所以我们用dp[n][n][k][m]来记录状态 前两维n n 代表当前坐标 k记录转弯几次 m记录方向 当m=0 记没改变方向 当m=1 为改变了方向
因为要用到矩阵边界 所以我们要预处理 m为0时的价值 具体看代码
解法1
#include <stdio.h> #include <iostream> #include <string.h> #define INF 0x3f3f3f3f using namespace std; int T,n; int a[105][105]; int dp[105][105][20][2]; int main(int argc, char const *argv[]) { ios::sync_with_stdio(false); cin >> T; while(T--){ cin >> n; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin >> a[i][j]; //memset(dp[i][j],INF,sizeof(dp[i][j])); } } memset(dp,INF,sizeof(dp)); dp[1][1][0][0]=a[1][1]; dp[1][1][0][1]=a[1][1]; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i>1) for(int k=0;k<=19;k++){ dp[i][j][k][0]=dp[i-1][j][k][0]+a[i][j]; } if(j>1) for(int k=0;k<=19;k++){ dp[i][j][k][1]=dp[i][j-1][k][1]+a[i][j]; } for(int k=1;k<=18;k++){ dp[i][j][k][1]=min(dp[i][j][k][1],dp[i][j][k-1][0]+(1<<(k-1))); dp[i][j][k][0]=min(dp[i][j][k][0],dp[i][j][k-1][1]+(1<<(k-1))); } } } int minn=INF; for(int a=0;a<=1;a++) for(int i=0;i<=18;i++){ minn=min(minn,dp[n][n][i][a]); } cout<<minn<<'\n'; } return 0; }
解法2 其实思路差不多 但是这个dp更容易理解
#include <stdio.h> #include <iostream> #include <string.h> #define INF 0x3f3f3f3f using namespace std; int T,n; int a[105][105]; int dp[105][105][20][2]; int main(int argc, char const *argv[]) { ios::sync_with_stdio(false); cin >> T; while(T--){ cin >> n; memset(dp,INF,sizeof(dp)); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ cin >> a[i][j]; //memset(dp[i][j],INF,sizeof(dp[i][j])); } } dp[0][1][0][0]=0; dp[1][0][0][1]=0; for(int i=1;i<=n;i++){ dp[1][i][0][1]=dp[1][i-1][0][1]+a[1][i]; dp[i][1][0][0]=dp[i-1][1][0][0]+a[i][1]; } for(int i=2;i<=n;i++){ for(int j=2;j<=n;j++){ for(int k=1;k<=18;k++){ // printf("%d\n",dp[i][j][k][0]); dp[i][j][k][1]=min(dp[i][j-1][k][1],dp[i][j-1][k-1][0]+(1<<(k-1)))+a[i][j]; dp[i][j][k][0]=min(dp[i-1][j][k][0],dp[i-1][j][k-1][1]+(1<<(k-1)))+a[i][j]; } } } int minn=INF; for(int a=0;a<=1;a++) for(int i=0;i<=18;i++){ minn=min(minn,dp[n][n][i][a]); // printf("%d\n",dp[n][n][i][a]); } cout<<minn<<'\n'; } return 0; }
人十我百 人百我万