mirror of
https://gitcode.com/Zengtudor/alg2025.git
synced 2025-12-16 20:23:00 +00:00
perf(P7297): 优化Dijkstra算法实现并添加注释
使用二分查找优化相邻节点的查找过程,提高算法效率 调整Dijkstra逻辑使其更符合标准实现 添加必要注释说明代码意图和优化点
This commit is contained in:
parent
3a44351971
commit
5aba1b0bab
@ -7,7 +7,10 @@
|
||||
#include <istream>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
using ll = int;
|
||||
// 引入这个头文件以使用 abs
|
||||
#include <cmath>
|
||||
|
||||
using ll = int; // 距离不会爆int,用int更快一点
|
||||
|
||||
const ll maxn=5e4+5,maxk=51,inf=1e9+7;
|
||||
ll n,k,b[maxn];
|
||||
@ -21,7 +24,7 @@ struct P{
|
||||
return step>o.step;
|
||||
}
|
||||
};
|
||||
#define printf
|
||||
|
||||
int main(){
|
||||
std::iostream::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
@ -34,6 +37,8 @@ int main(){
|
||||
classp[b[i]].emplace_back(i);
|
||||
vis[i]=inf;
|
||||
}
|
||||
// 注意:classp 中的下标天然就是有序的(从小到大),所以不需要额外排序
|
||||
|
||||
for(ll i=1;i<=k;i++){
|
||||
for(ll j=1;j<=k;j++){
|
||||
char tmp;
|
||||
@ -43,27 +48,57 @@ int main(){
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::priority_queue<P> pq;
|
||||
pq.emplace(1,0);
|
||||
// vis[1] = 0; // 严谨的Dijkstra最好在这里初始化,不过你的逻辑在下面判断也可以
|
||||
|
||||
while(pq.size()){
|
||||
auto[now,step]=pq.top();
|
||||
pq.pop();
|
||||
if(vis[now]!=inf)continue;
|
||||
vis[now]=std::min(step,vis[now]);
|
||||
printf("dij now=%lld, step=%lld\n",now,step);
|
||||
|
||||
// 这里的逻辑稍微调整一下,符合标准Dijkstra
|
||||
if(vis[now]!=inf) continue;
|
||||
vis[now]=step;
|
||||
|
||||
if(now==n){
|
||||
std::cout<<step<<"\n";
|
||||
return 0;
|
||||
}
|
||||
for(ll i:edg[b[now]]){
|
||||
for(ll p:classp[i]){
|
||||
if(p==now)continue;
|
||||
printf("%lld goto %lld\n",b[now],i);
|
||||
ll nstep=step+std::abs(p-now);
|
||||
if(nstep>vis[p])continue;
|
||||
pq.emplace(p,step+std::abs(p-now));
|
||||
|
||||
// --- 修改开始 ---
|
||||
for(ll target_breed : edg[b[now]]){
|
||||
// 获取目标品种的所有位置列表
|
||||
const auto& vec = classp[target_breed];
|
||||
if(vec.empty()) continue;
|
||||
|
||||
// 1. 找右边最近的一个 (第一个 > now 的位置)
|
||||
auto it = std::upper_bound(vec.begin(), vec.end(), now);
|
||||
if(it != vec.end()){
|
||||
ll p = *it;
|
||||
ll nstep = step + std::abs(p - now);
|
||||
// 只有当新路径更短,且该点未被“关闭”(未vis)时才入队
|
||||
// 注意:你之前的逻辑里 vis[p] 初始化是 inf,所以用 nstep < vis[p] 没问题
|
||||
// 但要注意 vis 在你的代码里既做“已访问标记”又存“最短路”。
|
||||
// 更安全的写法是只判断是否更优,因为如果 vis[p] 已经是更小的值,这里就不会进
|
||||
if(vis[p] == inf) {
|
||||
pq.emplace(p, nstep);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 找左边最近的一个 (第一个 < now 的位置)
|
||||
// lower_bound 是 >= now,所以它的前一个就是 < now
|
||||
auto it_l = std::lower_bound(vec.begin(), vec.end(), now);
|
||||
if(it_l != vec.begin()){
|
||||
it_l--; // 往前移一位
|
||||
ll p = *it_l;
|
||||
ll nstep = step + std::abs(p - now);
|
||||
if(vis[p] == inf) {
|
||||
pq.emplace(p, nstep);
|
||||
}
|
||||
}
|
||||
}
|
||||
// --- 修改结束 ---
|
||||
}
|
||||
std::cout<<"-1\n";
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user