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<<'
';
}
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
",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
",dp[n][n][i][a]);
}
cout<<minn<<'
';
}
return 0;
}