【BZOJ1975】【SDOI2010】魔法豬學院 [A*搜索]

魔法豬學院

Time Limit: 10 Sec  Memory Limit: 64 MB
[Submit][Status][Discuss]

Description

  iPig在假期來到了傳說中的魔法豬學院,開始爲期兩個月的魔法豬訓練。
  通過了一週理論知識和一週基本魔法的學習以後,iPig對豬世界的世界本原有了不少的瞭解:衆所周知,世界是由元素構成的;元素與元素之間能夠互相轉換;能量守恆……。
  iPig 今天就在進行一個麻煩的測驗。
  iPig 在以前的學習中已經知道了不少種元素,並學會了能夠轉化這些元素的魔法,每種魔法須要消耗 iPig 必定的能量。
  做爲 PKU 的頂尖學豬,讓 iPig 用最少的能量完成從一種元素轉換到另外一種元素……等等,iPig 的魔法導豬可沒這麼笨!
  這一次,他給 iPig 帶來了不少 1 號元素的樣本,要求 iPig 使用學習過的魔法將它們一個個轉化爲 N 號元素,爲了增長難度,要求每份樣本的轉換過程都不相同。
  這個看似困難的任務實際上對 iPig 並無挑戰性,由於,他有堅實的後盾……如今的你呀!
  注意,兩個元素之間的轉化可能有多種魔法,轉化是單向的。
  轉化的過程當中,能夠轉化到一個元素(包括開始元素)屢次,可是一但轉化到目標元素,則一份樣本的轉化過程結束。
  iPig 的總能量是有限的,因此最多可以轉換的樣本數必定是一個有限數。具體請參看樣例。 php

Input

  第一行三個數 N、M、E 表示iPig知道的元素個數(元素從 1 到 N 編號)、iPig已經學會的魔法個數和iPig的總能量。
  後跟 M 行每行三個數 si、ti、ei 表示 iPig 知道一種魔法,消耗 ei 的能量將元素 si 變換到元素 ti 。

Output

  一行一個數,表示最多能夠完成的方式數。輸入數據保證至少能夠完成一種方式。

Sample Input

  4 6 14.9
  1 2 1.5
  2 1 1.5
  1 3 3
  2 3 1.5
  3 4 1.5
  1 4 1.5

Sample Output

  3

HINT

  佔總分不小於 10% 的數據知足 N <= 6,M<=15。
  佔總分不小於 20% 的數據知足 N <= 100,M<=300,E<=100且E和全部的ei均爲整數(能夠直接做爲整型數字讀入)。
  全部數據知足 2 <= N <= 5000,1 <= M <= 200000,1<=E<=107,1<=ei<=E,E和全部的ei爲實數。
ios

Main idea

  詢問第一個知足1~k短路的和>E的k。ide

Solution

  求k短路,直接運用A*搜索便可,把T->每一個點的最短路當作估價便可。學習

Code

 1 #include<iostream>  
 2 #include<string>  
 3 #include<algorithm>  
 4 #include<cstdio>  
 5 #include<cstring>  
 6 #include<cstdlib>  
 7 #include<cmath>
 8 #include<queue>
 9 using namespace std;  10 typedef long long s64;  11  
 12 const int ONE = 205000;  13 const int POI = 5500;  14 const double INF = 1e18;  15  
 16 int n,m;  17 int S,T;  18 double dist[POI],w[ONE],E;  19 bool vis[POI];  20 int next[ONE],first[POI],go[ONE],tot;  21 int Ans;  22  
 23 struct point  24 {  25         int x,y; double z;  26 }a[ONE];  27  
 28 struct power  29 {  30         int x; double real;  31         bool operator <(const power &a) const
 32  {  33             return a.real + dist[a.x] < real + dist[x];  34  }  35 };  36  
 37 inline int get()  38 {  39         int res=1,Q=1;  char c;  40         while( (c=getchar())<48 || c>57)  41         if(c=='-')Q=-1;  42         if(Q) res=c-48;  43         while((c=getchar())>=48 && c<=57)  44         res=res*10+c-48;  45         return res*Q;  46 }  47  
 48 void Add(int u,int v,double z)  49 {  50         next[++tot]=first[u];   first[u]=tot;   go[tot]=v;  w[tot]=z;  51 }  52  
 53 void SPFA(int x)  54 {  55         queue <int> q;  56  q.push(x);  57         for(int i=S;i<=T;i++) dist[i] = INF;  58         vis[x] = 1; dist[x] = 0;  59         while(!q.empty())  60  {  61             int u = q.front(); q.pop();  62             for(int e=first[u];e;e=next[e])  63  {  64                 int v = go[e];  65                 if(dist[v] > dist[u] + w[e])  66  {  67                     dist[v] = dist[u] + w[e];  68                     if(!vis[v]) vis[v] = 1, q.push(v);  69  }  70  }  71             vis[u] = 0;  72  }  73 }  74  
 75 void Astar()  76 {  77         priority_queue <power> q;  78         q.push( (power){S, 0} );  79         while(!q.empty())  80  {  81             power u = q.top(); q.pop();  82             if(u.x == T) {E -= u.real; if(E < 0) return; Ans++;}  83             if(u.real + dist[u.x] > E) continue;  84             for(int e=first[u.x]; e; e=next[e])  85                 q.push( (power){go[e], u.real+w[e]} );  86              
 87  }  88 }  89  
 90 int main()  91 {  92         n=get();    m=get();    scanf("%lf",&E);  93         S=1,    T=n;  94         for(int i=1;i<=m;i++)  95  {  96             a[i].x=get();   a[i].y=get();   scanf("%lf",&a[i].z);  97  Add(a[i].y, a[i].x, a[i].z);  98  }  99  SPFA(T); 100          
101         memset(first,0,sizeof(first));  tot=0; 102         for(int i=1;i<=m;i++) Add(a[i].x,a[i].y,a[i].z); 103          
104  Astar(); 105          
106         printf("%d",Ans); 107 }
View Code
相關文章
相關標籤/搜索