·马里奥n次解救了公主,现在需要从魔王的宫殿返回。
·英文题,述大意:
给定一个点数不超过100的无向图,其中的点分为两类:乡村和城堡。
输入A个乡村,B个城堡(乡村编号1~A,城堡编号A+1~B),并给出m条无向路径及其需要花费的时间。不过还输入了K,L,表示马里奥有一双可以使用K次的高级鞋子,使用一次可前往原本L时间内的所有地方(一瞬间)。不过有一个限制条件是若使用鞋子加速,不能够穿过城堡(注意,是穿过,到达城堡是可以的)。询问从城堡A+B回到乡村1的最短时间。
·分析:
高级鞋子是一个很高级的东西。首先发现如果写最短路算法,那么需要两种路径更新:①正常行走②瞬间移动。但一般的最短路算法都是相邻点之间走来走去,这为瞬间移动的状态更新带来了极大的不便。所以将两种状态更新不加处理地写入同一个最短路算法是不明智之举。
·先预处理一种情况得的最短路。另一种情况在前一情况的辅助下进行更新。如果我们能够预先知道不穿过城堡的情况下每条路径的正常行走需要花费的时间,在来抉择这一段路需不需要用鞋子瞬移代替(当然,必须提醒的是,城堡之间也是可以用鞋子的,不要读错题啦)。任意两点之间的最短路径,让我们想到使用Floyd,要让不穿过城堡,即使得更新中继点不能为城堡就可以了。
·接下来的处理就很常规了。我们需要定义新状态来组成点,以表示当前还有t次使用鞋子的机会,已经走到了u点,即f[t][u]。状态更新就两种方式:
①f[t][u]+(路径时间)----->f[t][v]:表示正常行走
②f[t][u]+0------>f[t-1][v]:使用魔法鞋子
·大米饼使用的是SPFA,卡到了Vjudge这道题的第一名(now)。
1 #include<queue>
2 #include<stdio.h>
3 #include<algorithm>
4 #define inf 1000000000
5 #define go(i,a,b) for(int i=a;i<=b;i++)
6 using namespace std;const int N=102;
7 struct State{int u,t;}U;queue<State>q;
8 int T,A,B,m,L,K,n,u,v,w,g[N][N],f[11][N],*F;bool inq[N][11];
9 int main(){scanf("%d",&T);while(scanf("%d%d%d%d%d",&A,&B,&m,&L,&K),n=A+B,T--)
10 {
11 go(i,1,n){go(j,1,n)g[i][j]=inf;
12 go(j,0,K)f[j][i]=inf,inq[i][j]=0;}
13 go(i,1,m)scanf("%d%d%d",&u,&v,&w),g[v][u]=g[u][v]=w;
14 go(k,1,A)go(i,1,n)go(j,1,n)g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
15
16 inq[n][K]=1;f[K][n]=0;q.push((State){n,K});while(!q.empty())
17 {
18 U=q.front();q.pop();inq[U.u][U.t]=0;F=f[U.t];
19 go(i,1,n)
20 {
21 if(F[i]>F[U.u]+g[U.u][i])F[i]=F[U.u]+g[U.u][i],
22 !inq[i][U.t]?q.push((State){i,U.t}),inq[i][U.t]=1:1;
23 if(U.t&&g[U.u][i]<=L&&f[U.t-1][i]>F[U.u])f[U.t-1][i]=F[U.u],
24 !inq[i][U.t-1]?q.push((State){i,U.t-1}),inq[i][U.t-1]=1:1;
25 }
26 }
27 int ans=inf;go(i,0,K)ans=min(ans,f[i][1]);printf("%d
",ans);
28 }return 0;}//Paul_Guderian
·事后发现,这道题的点数较少,K无比地小。我们可以对程序稍做改进,可以达到更快的速度。我们的新方式是,queue只需要存储节点,无需记录时间。对于每个出队节点,枚举它的所有可能时间进行状态更新,这样减少了搜索的层数。
1 #include<queue>
2 #include<stdio.h>
3 #include<algorithm>
4 #define go(i,a,b) for(int i=a;i<=b;i++)
5 #define inf 100000000
6 using namespace std;const int N=102;queue<int>q;
7 int T,A,B,m,L,K,n,u,v,w,g[N][N],f[11][N],*F;bool inq[N];
8 int main(){scanf("%d",&T);while(scanf("%d%d%d%d%d",&A,&B,&m,&L,&K),n=A+B,T--)
9 {
10 go(i,1,n){go(j,1,n)g[i][j]=inf;
11 go(j,0,K)f[j][i]=inf;inq[i]=0;}
12 go(i,1,m)scanf("%d%d%d",&u,&v,&w),g[v][u]=g[u][v]=w;
13 go(k,1,A)go(i,1,n)go(j,1,n)g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
14
15 f[K][n]=0;q.push(n);while(!q.empty())
16 {
17 int u=q.front();q.pop();inq[u]=0;
18 go(i,1,n){if(i==u)continue;go(j,0,K)
19 {F=f[j];
20 if(F[i]>F[u]+g[u][i])F[i]=F[u]+g[u][i],
21 !inq[i]?q.push(i),inq[i]=1:1;
22 if(j&&g[u][i]<=L&&f[j-1][i]>F[u])f[j-1][i]=F[u],
23 !inq[i]?q.push(i),inq[i]=1:1;
24 }}
25 }
26 int ans=inf;go(i,0,K)ans=min(ans,f[i][1]);printf("%d
",ans);
27 }return 0;}//Paul_Guderian
那不灭不羁的倔强灵魂,还要经历多少风霜。——汪峰《不经意间》