题干:
徒弟的下山之路
终于到了出师的日子,徒弟需要从山顶的纯阳宫找一条花费最少时间的下山之路。
这座山用一个三角形来表示,从山顶依次向下有n层,第i层有i个可移动的位置,出口在最下层的左边。例如有一座5层的山:
此示例中出口为最下层最左边的1所在位置。山上每个数字代表徒弟路过这个位置需要花费的时间,徒弟下山总时间为路径上数字之和。
徒弟每次可以往左、右、左下、右下四个方向移动,例如徒弟位于第3层的数字5时可以向左走到4,向右走到6;也可以向左下走到1,向右下走到7;
又如徒弟位于第3层的数字6时,可以向左走到5,无法向右;也可以向左下走到7,向右下走到8;
输入格式
第一行一个整数n,表示山的高度
接下来n行,第i行有i个整数,表示徒弟经过这个位置需要的时间(路过每个位置花费的时间不超过10)。
数据约束
对于20%的数据,n=4
对于60%的数据,n<=10
对于100%的数据,n<=1000
输出格式
徒弟下山需要花费的最少时间
样例
input
5
1
3 2
4 5 6
9 1 7 8
1 1 4 5 6
output
11
思路:
开始以为就是一个简单的动态规划解决,结果发现不是这样哒,因为既可以从左边向右边走,又可以从右边向左边走,这里动态规划会循环处理。所以只能换个思路。
其实这就是一个简单的最短路问题,所以只要用求解最短路的方法求解就可以了。
自己套了一个dijkstra,可是最后三个点超时了。不知道原因,先放上代码。
#include <iostream>
#include <queue>
using namespace std;
int map[1001][1001];
int d[1001][1001];
int dy[4] = {
-1, 1, 0, 1}, dx[4] = {
0, 0, 1, 1};
struct P {
int x, y, cost;
bool operator<(const P &a) const {
return cost < a.cost; }
};
struct cmp {
bool operator()(P a, P b) {
return a.cost < b.cost; }
};
int main() {
int n;
cin >> n;
fill(map[0], map[0] + 1001 * 1001 + 1, 0x3f3f3f3f);
fill(d[0], d[0] + 1001 * 1001 + 1, 0x3f3f3fff);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
scanf("%d", &map[i][j]);
}
}
d[1][1] = map[1][1];
priority_queue<P, vector<P>, cmp> q;
P tmp;
tmp.x = 1, tmp.y = 1, tmp.cost = map[1][1];
q.push(tmp);
while (q.size()) {
P p = q.top();
q.pop();
if (d[p.x][p.y] < p.cost)
continue;
for (int i = 0; i < 4; i++) {
int tx = p.x + dx[i], ty = p.y + dy[i];
if (d[tx][ty] > map[tx][ty] + p.cost && tx >= 1 && ty >= 1) {
d[tx][ty] = map[tx][ty] + p.cost;
tmp.x = tx, tmp.y = ty, tmp.cost = d[tx][ty];
q.push(tmp);
}
}
}
cout << d[n][1] << endl;
return 0;
}
再放上大佬的代码:
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
int mapping[1005][1005],dp[1005][1005];
int directX[5]={
0,0,1,1};
int directY[5]={
-1,1,0,1};//方向数组
struct point{
int x,y,time;
}x;
int main(){
int n,i,j;
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=i;j++) scanf("%d",&mapping[i][j]);
x.x=x.y=1;
x.time=dp[1][1]=mapping[1][1];
queue<point> que;
que.push(x);
while(!que.empty()){
//bfs
x=que.front();
que.pop();
if(x.time>dp[x.x][x.y]) continue;
for(i=0;i<4;i++){
x.x+=directX[i];
x.y+=directY[i];
x.time+=mapping[x.x][x.y];//新结点
if(mapping[x.x][x.y]&&(dp[x.x][x.y]>x.time||!dp[x.x][x.y])){
//(没有越界&&(可以更新||没更新过))
que.push(x);
dp[x.x][x.y]=x.time;
}
x.time-=mapping[x.x][x.y];
x.x-=directX[i];
x.y-=directY[i]; //还原为原结点
}
}
cout<<dp[n][1]<<endl;
return 0;
}