1. 程式人生 > >POJ1062

POJ1062

return == temp -a 題目 || math stream hide

題目鏈接:http://poj.org/problem?id=1062

解題思路:

  枚舉區間+Dijkstra

  一開始理解錯了題意,WA了好久。後來參考題解才AC了。

  把每一樣物品看成一個點,由物品A換到物品B看成從A指向B的邊,這樣一來就把問題轉換成最短路問題了,具體實現看代碼吧。。。關鍵是枚舉區間這一個細節。

技術分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cmath>
 5 #include <algorithm>
 6
using namespace std; 7 const int inf=0xfffffff; 8 const int maxn=100+10; 9 int thing[maxn],ranks[maxn],vis[maxn],d[maxn]; 10 vector<pair<int,int> > vc[maxn]; //a,b ,ma[maxn],mi[maxn] 11 int road[maxn][maxn]; 12 int M,N,t; 13 int dijkstra(int l,int r){ 14 for(int i=1;i<=N;i++) {
15 vis[i]=0; 16 d[i]=inf; 17 } 18 d[1]=thing[1]; 19 while(1){ 20 int v=-1; 21 for(int u=1;u<=N;u++){ 22 if(!vis[u]&&(v==-1||d[u]<d[v])) v=u; 23 } 24 if(v==-1) break; 25 vis[v]=1; 26 for(int u=1;u<=N;u++){
27 if(ranks[u]<=r&&ranks[u]>=l&&d[u]>d[v]+road[v][u]-thing[v]){ 28 d[u]=d[v]+road[v][u]-thing[v]; 29 } 30 } 31 } 32 int ans=inf; 33 for(int i=1;i<=N;i++){ 34 if(ans>d[i]) ans=d[i]; 35 } 36 return ans; 37 } 38 int main(){ 39 scanf("%d%d",&M,&N); 40 for(int i=1;i<=N;i++){ 41 scanf("%d%d%d",&thing[i],&ranks[i],&t); 42 while(t--){ 43 int a,b; 44 scanf("%d%d",&a,&b); 45 vc[i].push_back(make_pair(a,b)); 46 } 47 } 48 for(int i=1;i<=N;i++){ 49 for(int j=i;j<=N;j++){ 50 if(i==j) 51 road[i][j]=thing[i]; 52 else 53 road[i][j]=road[j][i]=inf; 54 } 55 } 56 for(int i=1;i<=N;i++){ 57 for(int j=0;j<vc[i].size();j++){ 58 int a=vc[i][j].first,b=vc[i][j].second; 59 if(abs(ranks[a]-ranks[i])>M) continue; 60 road[i][a]=b+thing[a]; 61 } 62 } 63 int ans=inf; 64 for(int i=ranks[1]-M;i<=ranks[1];i++){ 65 int temp=dijkstra(i,i+M); 66 if(temp<ans) ans=temp; 67 } 68 69 70 printf("%d\n",ans); 71 return 0; 72 }
View Code

POJ1062