From 5aba1b0bab2ee7474ec1fba27526ef283eb94525 Mon Sep 17 00:00:00 2001 From: Zengtudor Date: Thu, 20 Nov 2025 22:45:27 +0800 Subject: [PATCH] =?UTF-8?q?perf(P7297):=20=E4=BC=98=E5=8C=96Dijkstra?= =?UTF-8?q?=E7=AE=97=E6=B3=95=E5=AE=9E=E7=8E=B0=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使用二分查找优化相邻节点的查找过程,提高算法效率 调整Dijkstra逻辑使其更符合标准实现 添加必要注释说明代码意图和优化点 --- src/11/13/P7297.cpp | 59 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/src/11/13/P7297.cpp b/src/11/13/P7297.cpp index c7a950f..e7e94ce 100644 --- a/src/11/13/P7297.cpp +++ b/src/11/13/P7297.cpp @@ -7,7 +7,10 @@ #include #include #include -using ll = int; +// 引入这个头文件以使用 abs +#include + +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

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<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"; } \ No newline at end of file