有一说一,如果这道题用dfs不会报超时错误的话,对我来说还是比较简单的,但事与愿违,dfs确实不好做这道题,计算量太大,很容易超时。
当然,凡是能用dfs做的且超时,用dp做基本都能解,可能我个人对dp不是很熟练,所以写起来有点磕磕绊绊。
思路:
dp数组的意义还是很好理解的,就是第1行到 第 i 行 第 j 列所用的最小代价。
ps:这里难就难在路径太多,数值太多,让人有点晕- -
动规五部曲:
1.dp数组---含义见上;
2.初始化----显然第一行到自己这一行的代价是它本身;
3.递推公式:重点!!!
dp[i][j]----表示到 第 i 行 第 j 列的最小值;则该值由两个方向可以得到,一个是选择当前节点作为路径节点加入到路径中,另一个就是不选择当且节点为路径节点,而是沿用之前选择过的结点。两者作比较,选择最小的。
dp[i][j]=min(dp[i][j],dp[i-1][j]+moveCost[grid[i-1][k]][j]+grid[i][j]);
注意:此时有三层循环 i j 表示当前 行列,k代表上一轮选择的列
class Solution {
public:
int res=INT_MAX;
int minPathCost(vector<vector<int>>& grid, vector<vector<int>>& moveCost) {
//dp[i][j] 数组的含义:第一行 到 第 i 行 第 j 列花费的最小代价
vector<vector<int>>dp(grid.size(),vector<int>(grid[0].size(),INT_MAX));
//初始化
for (int j = 0; j < grid[0].size(); j++)dp[0][j] = grid[0][j];
//递推公式
//dp[i][j] = min(dp[i][j], dp[i-1][j] +moveCost[grid[i-1][j]][j]);
//遍历顺序 从前到后
for (int i = 1; i < grid.size(); i++)
{
for (int j = 0; j < grid[i].size(); j++) //表示 一个结点
{
for (int k = 0; k < grid[i].size(); k++) //表示结点所在列
{
dp[i][j] = min(dp[i][j], dp[i - 1][k] + moveCost[grid[i - 1][k]][j] + grid[i][j]);
}
}
}
for (int j = 0; j < grid[0].size(); j++)
res = min(res, dp[grid.size() - 1][j]);
return res;
//打印dp
}
};
————————————————此处可不看—————————————————————
也让我沾一下我的dfs吧,花了老鼻子劲写的,除了数据大跑不动以外,小数据量还是对的,让它见见外面的世界 ~
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int result_1 = 0;
int result_2 = 0;
int result;
int minnum = INT_MAX;
void dfs(vector<vector<int>>& grid, vector<vector<int>>& moveCost, int p_val, vector<int>& v, int x, int y)
{
if (x == grid.size() - 1&&v.size()==grid.size())
{
result = result_1 + result_2;
minnum = minnum > result ? result : minnum;
return;
}
for (int i = x + 1; i < grid.size(); i++){
for (int j = 0; j < grid[0].size(); j++)
{
result_1 += moveCost[p_val][j];
result_2 += grid[i][j];
v.push_back(p_val);
dfs(grid, moveCost, grid[i][j], v, i, j);
v.pop_back();
// result -= (grid[i][j]+ moveCost[p_val][j]);
result_2 -= grid[i][j];
result_1 -= moveCost[p_val][j];
}
}
return;
}
int minPathCost(vector<vector<int>>& grid, vector<vector<int>>& moveCost) {
vector<int>v;
for (int i = 0; i < grid[0].size(); i++)
{
result_2 += grid[0][i];
v.push_back(grid[0][i]);
dfs(grid, moveCost, grid[0][i], v, 0, i);
v.pop_back();
result_2 -= grid[0][i];
}
return minnum;
}
int main()
{
int g_row, g_col, c_row, c_col;
cin >> g_row >> g_col >> c_row >> c_col;
vector<vector<int>>grid(g_row, vector<int>(g_col, 0));
vector<vector<int>>moveCost(c_row, vector<int>(c_col, 0));
for (int i = 0; i < g_row; i++)
{
for (int j = 0; j < g_col; j++)
{
cin >> grid[i][j];
}
}
for (int i = 0; i < c_row; i++)
{
for (int j = 0; j < c_col; j++)
{
cin >> moveCost[i][j];
}
}
minPathCost(grid, moveCost);
cout << minnum;
return 0;
动规得努力啊!!!!