题目链接: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 }
时间: 2024-11-04 22:21:52