[题解]UVA10269 Adventure of Super Mario
链接:http://vjudge.net/problem/viewProblem.action?id=24902
描述:由城镇、村子和双向边组成的图,从A+B走到1,要求最短路。有K次瞬移的机会,距离不超过L,且不能经过城镇。
思路:一个图上的DP。首先floyd处理,然后做dp。
定义f[i][j]:从1到i还有j次瞬移机会,花费的最少的时间。
状态转移:f[i][j]=min{f[k][j]+dis[k][i],min{f[k][j-1]}}
边界处理:f[1][k]=0 和 f[i][0]=dis[1][i]
我的实现:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 #define MaxN 120 6 #define INF 100000 7 int f[MaxN][MaxN],dis[MaxN][MaxN]; 8 bool OK[MaxN][MaxN]; 9 int T,n,A,B,M,L,K; 10 inline void Get_int(int &Ret) 11 { 12 char ch; 13 bool flag=false; 14 for(;ch=getchar(),ch<'0'||ch>'9';) 15 if(ch=='-') 16 flag=true; 17 for(Ret=ch-'0';ch=getchar(),ch>='0'&&ch<='9';Ret=Ret*10+ch-'0'); 18 flag&&(Ret=-Ret); 19 } 20 inline void Read_Clean() 21 { 22 Get_int(A);Get_int(B);Get_int(M);Get_int(L);Get_int(K); 23 n=A+B; 24 memset(dis,0x3f,sizeof(dis)); 25 memset(OK,false,sizeof(OK)); 26 memset(f,0,sizeof(f)); 27 int i,x,y,l; 28 for(i=1;i<=M;++i) 29 { 30 Get_int(x);Get_int(y);Get_int(l); 31 dis[x][y]=dis[y][x]=l; 32 if(l<=L) 33 OK[x][y]=OK[y][x]=true; 34 } 35 } 36 void floyd() 37 { 38 int i,j,k; 39 for(k=1;k<=n;++k) 40 for(i=1;i<=n;++i) 41 for(j=1;j<=n;++j) 42 if(dis[i][j]>dis[i][k]+dis[k][j]) 43 { 44 dis[i][j]=dis[i][k]+dis[k][j]; 45 if(k<=A&&dis[i][j]<=L) 46 OK[i][j]=OK[j][i]=true; 47 } 48 } 49 void DP() 50 { 51 int i,j,k,tmp; 52 for(i=2;i<=n;++i) 53 f[i][0]=dis[1][i]; 54 for(i=2;i<=n;++i) 55 { 56 for(j=1;j<=K;++j) 57 { 58 tmp=INF; 59 for(k=1;k<i;++k) 60 { 61 if(OK[k][i]) 62 tmp=min(tmp,f[k][j-1]); 63 tmp=min(tmp,f[k][j]+dis[k][i]); 64 } 65 f[i][j]=tmp; 66 } 67 } 68 printf("%d\n",f[n][K]); 69 } 70 int main() 71 { 72 Get_int(T); 73 while(T--) 74 { 75 Read_Clean(); 76 floyd(); 77 DP(); 78 } 79 return 0; 80 }
PS.破题出现了困难,最开始除了暴搜什么思路都没有。之后在暴搜的基础上发现了解题方法。总的来说觉得这道题蛮难的,zyy的路还很长啊~~~