一开始写的最大生成树,但是没有注意到题目要求每一个石头只能跳一次,如果生成树长下面这样就不对了(从0开始跳,这个不可能是一次跳完的路径)
所以说,只能用贪心,贪心有几种方式,一种是升序排序,然后再高低来回跳就行了,另一种是建无向图跑最长路,最开始是直接dfs+贪心过了,然后用了dijkstra求最长路(dijkstra求不了最长路,但是此处保证确定好最长路的结点不会再被更新后也没问题,其实和dfs+贪心没区别),后来又用路径全部取为相反数然后用dijkstra(这个和之前的求最长路做法没区别,都要标记集合内的点不能再被更新)和spfa分别做了最短路(我傻了...因为建的图一定有环,但是spfa没法求带负环的最短路,直接会超时)
注意点:
- dijkstra没法求非负边权最长路,没法用在含负权边的图上
- 带正环没法求最长路(其中spfa直接T)
- 带负环没法求最短路
- bellman-ford/spfa可以用来判断负环
- bellman-ford可以用来求从源点到别的点不超过k条边的最短路
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 310;
#define int long long
#define PII pair<int, int>
int n;
int h[N];
int st[N];
vector<vector<PII>> g(N);
int dfs(int u){
st[u] = 1;
for(int i = g[u].size() - 1; i >= 0; i --){
if(st[g[u][i].second]) continue;
return g[u][i].first + dfs(g[u][i].second);
}
return 0;
}
signed main(){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> h[i];
for(int i = 0; i <= n; i ++){
for(int j = 0; j <= n; j ++)
g[i].push_back({(h[i] - h[j]) * (h[i] - h[j]), j});
sort(g[i].begin(), g[i].end());
}
cout << dfs(0) << endl;
return 0;
}