1, HDU 1548 A strange lift :http://acm.hdu.edu.cn/showproblem.php?pid=1548
这道题可以灰常巧妙的转换为一道最短路题目,对第i层,按钮数字为button[i],则如果满足相加<=N,则把i到i+button[i]的路径长度设为1(巧妙将按钮次数转换为路径长度),同理,相减如果满足>=1,则把i到i-button[i]的路径长度设为1.则最后输出终点的最短路的长度即可
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=0x3f3f3f3f; int n,a,b; int map[210][210],vis[210],dis[210]; int SPFA(){ for(int i=1;i<=n;i++){ dis[i]=INF; vis[i]=0; } queue<int> q; while(!q.empty()) q.pop(); dis[a]=0; vis[a]=1; q.push(a); while(!q.empty()){ int cur=q.front(); q.pop(); vis[cur]=0; for(int i=1;i<=n;i++) if(dis[i]>dis[cur]+map[cur][i]){ dis[i]=dis[cur]+map[cur][i]; if(!vis[i]){ vis[i]=1; q.push(i); } } } return dis[b]; } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&n) && n){ scanf("%d%d",&a,&b); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=INF; int x; for(int i=1;i<=n;i++){ scanf("%d",&x); if(i-x>=1) map[i][i-x]=1; if(i+x<=n) map[i][i+x]=1; } int ans=SPFA(); if(ans==INF) ans=-1; printf("%d ",ans); } return 0; }
另附BFS解法:
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; int n,a,b; int k[210],vis[210]; struct node{ int x,step; }; int BFS(){ queue<node> q; while(!q.empty()) q.pop(); node cur,next; cur.x=a, cur.step=0; vis[cur.x]=1; q.push(cur); while(!q.empty()){ cur=q.front(); q.pop(); if(cur.x==b) return cur.step; next.x=cur.x-k[cur.x]; next.step=cur.step+1; if(next.x>=1 && next.x<=n && !vis[next.x]){ vis[next.x]=1; q.push(next); } next.x=cur.x+k[cur.x]; if(next.x>=1 && next.x<=n && !vis[next.x]){ vis[next.x]=1; q.push(next); } } return -1; } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d",&n) && n){ scanf("%d%d",&a,&b); for(int i=1;i<=n;i++) scanf("%d",&k[i]); memset(vis,0,sizeof(vis)); int ans=BFS(); printf("%d ",ans); } return 0; }
2, HDU 3790 最短路径问题 : http://acm.hdu.edu.cn/showproblem.php?pid=3790
二维距离(路程,价格),优先判断路程…
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int VM=1010; const int EM=100010; const int INF=0x3f3f3f3f; struct Edge{ int to,nxt; int cap,cost; }edge[EM<<1]; int n,m,cnt,head[VM]; int src,des,dis[VM],pay[VM],vis[VM]; void addedge(int cu,int cv,int cw,int cc){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].cost=cc; edge[cnt].nxt=head[cu]; head[cu]=cnt++; } void SPFA(){ for(int i=1;i<=n;i++){ dis[i]=INF; pay[i]=INF; vis[i]=0; } queue<int> q; while(!q.empty()) q.pop(); dis[src]=0; pay[src]=0; vis[src]=1; q.push(src); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(dis[v]>dis[u]+edge[i].cap || (dis[v]==dis[u]+edge[i].cap && pay[v]>pay[u]+edge[i].cost)){ //二维距离(路程,价格),优先判断路程… dis[v]=dis[u]+edge[i].cap; pay[v]=pay[u]+edge[i].cost; if(!vis[v]){ vis[v]=1; q.push(v); } } } } } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ if(n==0 && m==0) break; cnt=0; memset(head,-1,sizeof(head)); int u,v,d,p; while(m--){ scanf("%d%d%d%d",&u,&v,&d,&p); addedge(u,v,d,p); //因为是无向边,所以建双向图 addedge(v,u,d,p); } scanf("%d%d",&src,&des); SPFA(); printf("%d %d ",dis[des],pay[des]); } return 0; }
3, HDU 2066 一个人的旅行 : http://acm.hdu.edu.cn/showproblem.php?pid=2066
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int INF=0x3f3f3f3f; struct Edge{ int to,nxt; int cap; }edge[100010]; int T,S,D; int cnt,head[1100]; int src,des,dis[1100],vis[1100]; void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; } int SPFA(){ queue<int> q; while(!q.empty()) q.pop(); for(int i=0;i<=1001;i++){ dis[i]=INF; vis[i]=0; } dis[src]=0; vis[src]=1; q.push(src); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(dis[v]>dis[u]+edge[i].cap){ dis[v]=dis[u]+edge[i].cap; if(!vis[v]){ vis[v]=1; q.push(v); } } } } return dis[des]; } int main(){ //freopen("input.txt","r",stdin); while(~scanf("%d%d%d",&T,&S,&D)){ cnt=0; memset(head,-1,sizeof(head)); int u,v,w; while(T--){ scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } src=0, des=1001; while(S--){ scanf("%d",&v); addedge(src,v,0); } while(D--){ scanf("%d",&u); addedge(u,des,0); } int ans=SPFA(); printf("%d ",ans); } return 0; }
4, HDU 2112 HDU Today : http://acm.hdu.edu.cn/showproblem.php?pid=2112
trick:起点和终点有可能是同一点,坑爹呐。。。。。。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<queue> using namespace std; const int N=100010; const int INF=0x3f3f3f3f; struct Edge{ int to,nxt; int cap; }edge[N<<1]; int all,cnt,head[N]; int src,des,dis[N],vis[N]; void addedge(int cu,int cv,int cw){ edge[cnt].to=cv; edge[cnt].cap=cw; edge[cnt].nxt=head[cu]; head[cu]=cnt++; } int SPFA(){ queue<int> q; while(!q.empty()) q.pop(); for(int i=0;i<=all;i++){ dis[i]=INF; vis[i]=0; } dis[src]=0; vis[src]=1; q.push(src); while(!q.empty()){ int u=q.front(); q.pop(); vis[u]=0; for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(dis[v]>dis[u]+edge[i].cap){ dis[v]=dis[u]+edge[i].cap; if(!vis[v]){ vis[v]=1; q.push(v); } } } } return dis[des]; } int main(){ //freopen("input.txt","r",stdin); int n; char str1[40],str2[40]; char s[40],t[40]; map<string,int> mp; while(~scanf("%d",&n) && n!=-1){ cnt=0; memset(head,-1,sizeof(head)); all=1; mp.clear(); scanf("%s%s",s,t); mp[s]=all++; //起点和终点有可能是同一点 src=mp[s]; if(mp[t]==0) mp[t]=all++; des=mp[t]; int w; while(n--){ scanf("%s%s%d",str1,str2,&w); if(mp[str1]==0) mp[str1]=all++; if(mp[str2]==0) mp[str2]=all++; addedge(mp[str1],mp[str2],w); addedge(mp[str2],mp[str1],w); } int ans=SPFA(); if(ans==INF) ans=-1; printf("%d ",ans); } return 0; }