这道题比较经典了。建图时用g[0][i] 表示不用替代物品获得编号为i的物品所需的金币,
g[j][i]代表用编号为j的物品替代获得编号为i的物品所需要的金币,然后在M的限制范
围内进行所有可能的交易,最后获得其最小值,一共需要做m次dij。
/*Accepted 228K 0MS C++ 1600B 2012-07-26 15:16:49*/ #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; const int MAXN = 1 << 7; const int inf = 0x3f3f3f3f; int M, N, g[MAXN][MAXN], lev[MAXN]; typedef pair< int, int> pii; void ReadGragh() { for( int i = 0; i <= N; i ++) for( int j = 0; j <= N; j ++) g[i][j] = inf; for( int i = 1; i <= N; i ++) { int x; scanf( "%d%d%d", &g[0][i], &lev[i], &x); while( x --) { int j; scanf( "%d", &j); scanf( "%d", &g[j][i]); } } } int Dijkstra( int l, int r) { priority_queue< pii, vector<pii>, greater<pii> > q; int dist[MAXN] = {0}; for( int i = 1; i <= N; i ++) dist[i] = inf; q.push( make_pair(0, 0) ); while( !q.empty() ) { pii u = q.top(); q.pop(); int x = u.second; if( u.first > dist[x]) continue; if( x == 1) return dist[1]; for( int i = 1; i <= N; i ++) { if( l <= lev[i] && lev[i] <= r && dist[i] > dist[x] + g[x][i]) { dist[i] = dist[x] + g[x][i]; q.push( make_pair( dist[i], i)); } } } return 0; } int main() { int ans; while( scanf( "%d%d", &M, &N) == 2) { ans = inf; ReadGragh(); for( int i = lev[1] - M; i <= lev[1]; i ++) //在M的范围内交易 { ans = min( ans, Dijkstra( i, i + M) ); } printf( "%d\n", ans); } return 0; }