题目链接:点这里~
题目大意
求从点(1,1)走到点(r,c)的最少花费。
操作是向左走花费a[x-1][y],向右走花费a[x][y],向下走花费b[x][y],向上走,花费是向上走的步数+1。
思路
比赛的时候先是从(1,1)开始跑dfs但是肯定T呀,然后是从(1,1)开始跑bfs但还是T了4个点,最后居然是跑一个优先队列,dist表示从(1,1)走到本地的最小花费,每次优先队列弹出dist最小的更新其他点,跑到终点(r,c)就可以跳出。
ac代码
#include<bits/stdc++.h>
using namespace std;
int a[505][505], b[505][505], dp[505][505];
const int inf = 0x3f3f3f3f;
int r, c;
struct node{
int x, y, dist;
bool operator < (const node &a)const{
return a.dist < dist; //使得优先队列是小顶堆
}
};
void bfs(int x, int y){
priority_queue<node> q;
q.push({x, y});
while(q.size()){
x = q.top().x, y = q.top().y;
q.pop();
if(x == r && y == c) break; //跑到终点就退出
if(y + 1 <= c && dp[x][y] + a[x][y] < dp[x][y + 1]){ //往右走,更新右边
dp[x][y + 1] = dp[x][y] + a[x][y];
q.push({x,y+1, dp[x][y+1]});
}
if(y - 1 >= 1 && dp[x][y] + a[x][y - 1] < dp[x][y - 1]){ //往左走,更新左边
dp[x][y - 1] = dp[x][y] + a[x][y - 1];
q.push({x,y-1,dp[x][y-1]});
}
if(x+1 <= r && dp[x][y] + b[x][y] < dp[x+1][y]){ //往下走,更新下边
dp[x+1][y] = dp[x][y] + b[x][y];
q.push({x+1,y,dp[x+1][y]});
}
for(int i = 1; i < x; i ++){ //往上走,更新上边
if(dp[x][y] + x - i + 1 < dp[i][y]){
dp[i][y] = dp[x][y] + x - i + 1;
q.push({i, y,dp[i][y]});
}
}
}
}
int main(){
cin >> r >> c;
for(int i = 1; i <= r; i ++){
for(int j = 1; j < c; j ++){
cin >> a[i][j];
}
}
for(int i = 1; i < r; i ++){
for(int j = 1; j <= c; j ++){
cin >> b[i][j];
}
}
//初始化
memset(dp, inf, sizeof(dp));
dp[1][1] = 0;
bfs(1, 1);
cout << dp[r][c] << endl;
return 0;
}