最短路水题。
把每个点拆成0,1,2,3......k共k+1个点,表示到达该点时用了几次膜法(雾),然后再求最短路就好了,每次松弛的时候有两种,用或不用膜(划掉)魔法。
其实spfa的思想很像动规的。。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int inf=1e9; struct Edge{int to,next,v;}e[2005]; int d[55][55],k,head[55],cnt; bool inq[55][55]; void ins(int u,int v,int w){ e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].v=w; } void spfa(){ queue<int>q,qk; memset(d,0x3f,sizeof(d)); q.push(1);qk.push(0);d[1][0]=0; while(!q.empty()){ int u=q.front(),tk=qk.front();q.pop();qk.pop(); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(tk<k&&d[v][tk+1]>d[u][tk]+(e[i].v>>1)){ d[v][tk+1]=d[u][tk]+(e[i].v>>1); if(!inq[v][tk+1]){inq[v][tk+1]=true;q.push(v);qk.push(tk+1);} } if(d[v][tk]>d[u][tk]+e[i].v){ d[v][tk]=d[u][tk]+e[i].v; if(!inq[v][tk]){inq[v][tk]=true;q.push(v);qk.push(tk);} } } } } int main(){ int n,m;scanf("%d%d%d",&n,&m,&k); int u,v,w; while(m--){ scanf("%d%d%d",&u,&v,&w); ins(u,v,w);ins(v,u,w); } spfa(); int ans=inf; for(int i=0;i<=k;i++)ans=min(ans,d[n][i]); printf("%d",ans); return 0; }