转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题意:给出a个村庄,b个城堡,村庄的标号为1……a,城堡的标号为a+1……a+b。然后有m条无向边,每条边有个距离。某个人打算从a+b到1,然后他有一双神奇的鞋子,可以用k次,每次最多连续跑L。而且穿着鞋子的时候不能穿过城堡,到达城堡的时候只能停下,而且不能停留在路中间。只要停下来,就相当于用了一次鞋子。
今天做完TC,对于div1的450,是一个新接触的。在spfa中跑DP。有效的解决了图上DP的后效性问题。
yobobobo之后推荐了这个题,主要还是受TC的影响,才能想到正解。
首先预处理下穿鞋子跑一次的情况。
枚举所有点为起点,然后预处理从这个点穿着鞋子跑到达每一个点的最短距离。
而且注意:不能穿过城堡
在SPFA的时候,不会把城堡入队(除了城堡是起点)
之后dp[i][j]表示在i点时,鞋子还剩j次的最短距离。
DP过程扔进spfa里更新就行了。
对于每一个点,更新情况有两种。
首先不考虑鞋子,步行到下一个地方。
考虑用一次鞋子,枚举所有的点,进行转移。
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #include<stack> #include<string> #include<ctime> #include<queue> #define inf 0x3f3f3f3f #define M 10000005 #define N 40005 #define maxn 210005 #define eps 1e-8 #define zero(a) fabs(a)<eps #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define LL long long #define MOD 1000000007 #define sqr(a) ((a)*(a)) #define Key_value ch[ch[root][1]][0] #define test puts("OK"); #define pi acos(-1.0) #define lowbit(x) ((-(x))&(x)) #define HASH1 1331 #define HASH2 10001 #define C 240 #define vi vector<int> #define TIME 10 //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; struct Edge{ int v,w,next; }e[10005]; int t,a,b,m,l,k; int start[105],tot; int dist[105][105]; int dp[105][15]; void _add(int u,int v,int w){ e[tot].v=v;e[tot].w=w; e[tot].next=start[u]; start[u]=tot++; } void add(int u,int v,int w){ _add(u,v,w); _add(v,u,w); } void Init(){ queue<int>que; bool in[105]; mem(dist,0x3f); for(int i=1;i<=a+b;i++){ while(!que.empty()) que.pop(); mem(in,false); que.push(i); in[i]=true; dist[i][i]=0; while(!que.empty()){ int u=que.front(); que.pop(); in[u]=false; for(int r=start[u];r!=-1;r=e[r].next){ int v=e[r].v,w=e[r].w; if(dist[i][v]>dist[i][u]+w){ dist[i][v]=dist[i][u]+w; if(v<=a&&in[v]==false){ in[v]=true; que.push(v); } } } } } } int main(){ scanf("%d",&t); while(t--){ mem(start,-1); tot=0; scanf("%d%d%d%d%d",&a,&b,&m,&l,&k); for(int i=0;i<m;i++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w); } Init(); bool in[105]; mem(in,false); mem(dp,0x3f); queue<int>que; que.push(a+b); in[a+b]=true; dp[a+b][k]=0; while(!que.empty()){ int u=que.front(); que.pop(); in[u]=false; for(int i=0;i<=k;i++){ for(int r=start[u];r!=-1;r=e[r].next){ int v=e[r].v,w=e[r].w; if(dp[v][i]>dp[u][i]+w){ dp[v][i]=dp[u][i]+w; if(in[v]==false){ in[v]=true; que.push(v); } } } if(!i) continue; for(int v=1;v<=a+b;v++){ if(v!=u&&dist[u][v]<=l){ if(dp[v][i-1]>dp[u][i]){ dp[v][i-1]=dp[u][i]; if(in[v]==false){ in[v]=true; que.push(v); } } } } } } int ans=inf; for(int i=0;i<=k;i++) ans=min(ans,dp[1][i]); printf("%d\n",ans); } return 0; }
作者:ACM_cxlove 发表于2013-3-15 18:37:54 原文链接
阅读:58 评论:0 查看评论