探險家要用最少金幣娶到酋長女兒。物品編號 1..N(1 號為酋長承諾),每個物品有原價 P、主人等級 L、若干替代品 (T, V) 表示用物品 T 可按價 V 購買。交易規則:任意兩人等級差 > M 不得直接/間接交易;探險家初始無等級限制,但一旦與某等級交易,超出 M 範圍的等級將拒絕後續交易。求得到物品 1 的最小花費。
T → i 權重 V 表示用 T 換 i;虛擬源點 0 向每個物品 i 連邊權 P_i 表示直接買。[L_min, L_min+M] 內。L_min 為每個物品的等級,構建子圖只保留等級在 [L_min, L_min+M] 的點,跑 Dijkstra 求 0→1 最短路,取全局最小值。// 圖用鄰接矩陣 tu[u][v] 存儲最小權重
// price[i] 為從源點 0 到 i 的當前最短距離
// visit[i] 標記節點是否在當前等級窗口內且未最終確定
// 簡化版 Dijkstra(N≤100,O(N^2) 足夠):
for i=1..N: price[i]=tu[0][i];
repeat N times:
找未確定的 visit[j]=true 且 price[j] 最小的 u
visit[u]=false;
對所有 visit[v]=true: price[v]=min(price[v], price[u]+tu[u][v]);
答案為 price[1]
N 個等級窗口O(N^2)O(N^3) = 10^6 量級,極快。#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int tu[105][105], price[105], level[105];
bool visit[105];
int n, m;
int dijkstra() {
for(int i=1;i<=n;i++) price[i]=tu[0][i];
memset(visit, true, sizeof(visit));
visit[0]=false;
for(int iter=1; iter<=n; iter++){
int u=0, mn=1e9;
for(int j=1;j<=n;j++) if(visit[j] && price[j]>m>>n){
memset(tu,0,sizeof(tu));
for(int i=1;i<=n;i++){
int k; cin>>price[i]>>level[i]>>k;
tu[0][i]=price[i];
for(int j=0;j>v>>p;
tu[v][i]=p; // v -> i
}
}
int ans=1e9;
for(int i=1;i<=n;i++){
int L=level[i];
for(int j=1;j<=n;j++)
visit[j] = (level[j]>=L && level[j]<=L+m);
ans=min(ans, dijkstra());
}
cout<
本題巧妙結合「等級差約束」與「最短路」,通過枚舉等級窗口將動態約束轉化為靜態子圖,是圖論建模與約束處理的經典範例。