HDU_Steps6.2 最短路 HDU2544 HDU2112 HDU1385 HDU2923 HDU2722 HDU2377 HDU3191 HDU3399

来源:互联网 发布:好的交友软件 编辑:程序博客网 时间:2024/06/05 15:00

6.2.1 HDU2544 最短路 裸的dijkstra

6.2.2 HDU2112 HDU Today 数据规模小,map转字符串为数字点,然后dijkstra
6.2.3 HDU1385 Minimum Transport Cost

利用dijk的特性来记录路径,路径相等时比较当前路径和已存路径的字典序

#include <cstdio>#include <algorithm>#include <queue>#include <cstdlib>#include <string.h>#define MAXN 1001#define INF 1e9using namespace std;struct node{int v,i;node(int a,int b){v=a,i=b;}bool operator<(const node& n)const{return v>n.v;}}; int n,map[MAXN][MAXN],done[MAXN],d[MAXN],cost[MAXN],pre[MAXN];void outpath(int st,int en){if(pre[en]!=st)outpath(st,pre[en]);printf("-->%d",en);}int com(int st,int p1,int p2,int p){int l1=2,l2=2,s1[MAXN],s2[MAXN];s1[0]=p,s2[0]=p,s1[1]=p1,s2[1]=p2;while(p1!=st){s1[l1++]=pre[p1];p1=pre[p1];}while(p2!=st){s2[l2++]=pre[p2];p2=pre[p2];}/* 这个是对字典序错误的理解 并不是长度优先 if(l1>l2)return 0;else if(l1<l2)return 1;for(int i=l2-1;i>=0;i--){if(s1[i]>s2[i])return 0;else if(s1[i]<s2[i])return 1;}*/l1--,l2--;while(1){   if(s1[l1]>s2[l2]) return 0;   else if(s1[l1]<s2[l2]) return 1;   l1--,l2--;   if(l2<0) return 0;   else if(l1<0) return 1;}return 0;}void dij(int st,int en){if(st==en){printf("From %d to %d :\n",st,en);printf("Path: %d",st);printf("\nTotal cost : 0\n\n");return;}priority_queue<node> q;memset(done,0,sizeof done);memset(pre,-1,sizeof pre);for(int i=1;i<=n;i++)d[i]=INF;d[st]=0;q.push(node(d[st],st));while(!q.empty()){node nd=q.top();q.pop();int u=nd.i;if(done[u])continue;done[u]=1;for(int i=1;i<=n;i++){if(d[i]>=d[u]+map[u][i]+cost[i]){if(d[i]==d[u]+map[u][i]+cost[i]&&!com(st,u,pre[i],i))continue;d[i]=d[u]+map[u][i]+cost[i];pre[i]=u;q.push(node(d[i],i));}}}printf("From %d to %d :\n",st,en);printf("Path: %d",st);outpath(st,en);printf("\n"); printf("Total cost : %d\n\n",d[en]-cost[en]);}int main(){while(scanf("%d",&n),n){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){scanf("%d",&map[i][j]);if(map[i][j]==-1)map[i][j]=INF;}}for(int i=1;i<=n;i++)scanf("%d",&cost[i]); int st,en;while(scanf("%d%d",&st,&en)){if(st==-1&&en==-1)break;dij(st,en);}}}

6.2.4 HDU2923 Einbahnstrasse

FLOYD ,注意两点之间可能会有多条路,只记录权值最小的

#include <cstdio>#include <iostream>#include <map>#include <string>#include <string.h>using namespace std;string s,s2,s3,des[1005];map<string,int> mp;int n,c,r,ns,maps[105][105];int main(){int cas=1;while(cin>>n>>c>>r,n||c||r){ns=0;mp.clear();cin>>s;mp[s]=++ns;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)maps[i][j]=1e9;for(int i=0;i<c;i++){cin>>des[i];if(mp.count(des[i])==0)mp[des[i]]=++ns;}for(int i=0;i<r;i++){cin>>s>>s2>>s3;if(mp.count(s)==0)mp[s]=++ns;if(mp.count(s3)==0)mp[s3]=++ns;int t1=mp[s],t2=mp[s3];int ind=0,dis=0;while(s2[ind]<'0'||s2[ind]>'9')ind++;while(s2[ind]>='0'&&s2[ind]<='9')dis=dis*10+s2[ind]-'0',ind++;//可能会有多条路径,选最短的 if(s2[0]=='<'&&dis<maps[t2][t1])maps[t2][t1]=dis;if(s2[s2.length()-1]=='>'&&dis<maps[t1][t2])maps[t1][t2]=dis;}//直接FLOYD for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(maps[i][j]>maps[i][k]+maps[k][j])maps[i][j]=maps[i][k]+maps[k][j];}}}int res=0;for(int i=0;i<c;i++)res+=maps[1][mp[des[i]]]+maps[mp[des[i]]][1];printf("%d. %d\n",cas++,res);}} 


6.2.5 HDU2722 Here We Go(relians) Again

建图真的是很麻烦啊,一共(n+1)*(m+1)个点,建图后dijkstra就行了

#include <string.h>#include <cstdio>#include <queue>#define INF 1e9using namespace std;struct node{int v,i;node(int a,int b){v=a,i=b;}bool operator <(const node& a)const{return v>a.v;}};int n,m,map[500][500];int done[500],d[500];int dij(){priority_queue<node> q;memset(done,0,sizeof done);for(int i=1;i<=(n+1)*(m+1);i++)d[i]=INF;d[1]=0;q.push(node(d[1],1));while(!q.empty()){node nd=q.top();q.pop();int u=nd.i;if(done[u])continue;done[u]=1;for(int i=1;i<=(n+1)*(m+1);i++){if(d[i]>d[u]+map[u][i]){d[i]=d[u]+map[u][i];q.push(node(d[i],i));}}}if(d[(n+1)*(m+1)]==INF)return -1;else return d[(n+1)*(m+1)]; }int main(){char s[3];int v;while(scanf("%d%d",&n,&m),n||m){for(int i=1;i<=(n+1)*(m+1);i++)for(int j=1;j<=(n+1)*(m+1);j++)map[i][j]=INF;//input 建图很麻烦 一共(n+1)*(m+1)个点 int n1,n2;for(int i=1;i<=2*n+1;i++){if(i%2==1){for(int j=1;j<=m;j++){n1=(i/2)*(m+1)+j,n2=n1+1;scanf("%d%s",&v,s);if(v==0)continue;if(s[0]=='*')map[n1][n2]=map[n2][n1]=2520/v;else if(s[0]=='<')map[n2][n1]=2520/v;else if(s[0]=='>')map[n1][n2]=2520/v;}}else{for(int j=1;j<=m+1;j++){n1=(i/2-1)*(m+1)+j,n2=n1+m+1;scanf("%d%s",&v,s);if(v==0)continue;if(s[0]=='*')map[n1][n2]=map[n2][n1]=2520/v;else if(s[0]=='v')map[n1][n2]=2520/v;else if(s[0]=='^')map[n2][n1]=2520/v;}}}/*for(int i=1;i<=(n+1)*(m+1);i++){for(int j=1;j<=(n+1)*(m+1);j++){printf("%d  ",map[i][j]);}printf("\n");}*/int r=dij();if(r==-1)printf("Holiday\n");else printf("%d blips\n",r); }return 0;}


6.2.6 HDU2377 Bus Pass
看了半天才看懂题目的意思,就是给一张图,然后给一个公交路线。然后在地图中找一个点,使这个点到所有公交路线经过的点的最大距离最小。

从公交路线上的每个点BFS整幅图,就可以得到地图上所有点到这个公交点的距离,记录每个点到公交路线点集的最大距离,即为该点到公交路线的最大值,然后在这些点里选一个值最小的就可以了。

#include <cstdio>#include <queue>#include <string.h>#define INF 1e9using namespace std;int cas,nz,nr,mr[21];int map[10000][11],vis[10000],res[10000],u;void bfs(int st){memset(vis,0,sizeof vis);queue<int> q;q.push(st);vis[st]=1;while(!q.empty()){int nu=q.front();q.pop();for(int i=1;i<=map[nu][0];i++){int t=map[nu][i];if(!vis[t]){vis[t]=vis[nu]+1;q.push(t);}}}//跟新较大值为当前点到路线点集最远点的最近距离,不能到达点跟新为无穷大 for(int i=1;i<=10000;i++){if(!vis[i])res[i]=INF;else res[i]=max(res[i],vis[i]);}}int main(){scanf("%d",&cas);while(cas--){memset(map,0,sizeof map);memset(res,0,sizeof res);scanf("%d%d",&nr,&nz);for(int i=0;i<nr;i++){scanf("%d",&u);scanf("%d",&map[u][0]);for(int j=1;j<=map[u][0];j++)scanf("%d",&map[u][j]); }//对每个汽车经过点BFS,找出其它点到它的最短路径for(int i=1;i<=nz;i++){scanf("%d",&mr[i]);for(int j=1;j<=mr[i];j++){scanf("%d",&u);bfs(u);}}//找出到点集最远点距离最近的点 int r=INF,rind;for(int i=1;i<10000;i++){if(res[i]<r){r=res[i];rind=i;}}printf("%d %d\n",r,rind);}return 0;} 


6.2.7 HDU3191 How Many Paths Are There 求次短路条数

#include<iostream>#include<algorithm>#define N 55#define M 10000#define inf 0x7fffffffusing namespace std;int cnt[N][2],dis[N][2];bool h[N][2];int NE,head[N];int n,m;struct node{int next,v,w;node(){};node(int a,int b,int c){next=a;v=b;w=c;}}E[M];void init(){NE=0;memset(head,-1,sizeof(head));}void insert(int u,int v,int w){E[NE]=node(head[u],v,w);head[u]=NE++;}void dijkstra(int beg,int end){for(int i=0;i<=n;i++){dis[i][0]=dis[i][1]=inf;cnt[i][0]=cnt[i][1]=0;}memset(h,0,sizeof(h));dis[beg][0]=0;cnt[beg][0]=1;while(true){int u,flag;int Min=inf;for(int i=0;i<n;i++){if(!h[i][0]&&dis[i][0]<Min){Min=dis[i][0];u=i;flag=0;}else if(!h[i][1]&&dis[i][1]<Min){Min=dis[i][1];u=i;flag=1;}}if(u==end&&flag==1) break;if(Min==inf) break;h[u][flag]=1;for(int i=head[u];i!=-1;i=E[i].next){int v=E[i].v;int w=dis[u][flag]+E[i].w;if(dis[v][0]>w){if(dis[v][0]!=inf){dis[v][1]=dis[v][0];cnt[v][1]=cnt[v][0];}dis[v][0]=w;cnt[v][0]=cnt[u][flag];}else if(dis[v][0]==w)cnt[v][0]+=cnt[u][flag];else if(dis[v][1]>w){dis[v][1]=w;cnt[v][1]=cnt[u][flag];}else if(dis[v][1]==w)cnt[v][1]+=cnt[u][flag];}}printf("%d %d\n",dis[end][1],cnt[end][1]);}int main(void){int s,t;while(~scanf("%d%d%d%d",&n,&m,&s,&t)){init();while(m--){int x,y,w;scanf("%d%d%d",&x,&y,&w);insert(x,y,w);}dijkstra(s,t);}}


 


6.2.8 HDU3399 In Action DP+Dijkstra

破坏地图上的点,破坏的能量超过一半时系统被破坏

先用最短路求出到地图上每个点的最短路,即为到每个点消耗的最小花费,然后使用DP,01背包,重量为能量,权值为到每个点的花费。然后扫描一遍得到当背包被填充了一半以上时的最小花费和。

#include <cstdio>#include <string.h>#include <queue>#include <algorithm> #define MAXN 105#define INF 1e9using namespace std;struct node{int v,i;node(int a,int b){v=a,i=b;}bool operator<(const node& nd)const{return v>nd.v;}};int cas,n,m,u,v,w,tpow;int map[MAXN][MAXN],pow[MAXN],d[MAXN],done[MAXN],dd[MAXN*MAXN];void dij(){priority_queue<node> q;memset(done,0,sizeof done);for(int i=0;i<=n;i++)d[i]=INF;d[0]=0;q.push(node(d[0],0));while(!q.empty()){node nd=q.top();q.pop();int u=nd.i;if(done[u])continue;done[u]=1;for(int i=0;i<=n;i++){if(d[i]>d[u]+map[u][i]){d[i]=d[u]+map[u][i];q.push(node(d[i],i));}}}}int dp(){//DP求最小值 for(int i=0;i<=tpow;i++)dd[i]=INF; dd[0]=0;for(int i=1;i<=n;i++){for(int j=tpow;j>=pow[i];j--){dd[j]=min(dd[j],dd[j-pow[i]]+d[i]); }}//找出大于一半背包时的最小路径和 int res=INF;for(int i=tpow/2+1;i<=tpow;i++){res=min(res,dd[i]);}if(res<INF)return res;else return -1;}int main(){scanf("%d",&cas);while(cas--){scanf("%d%d",&n,&m);for(int i=0;i<=n;i++)for(int j=0;j<=n;j++)map[i][j]=INF;tpow=0;//Inputfor(int i=0;i<m;i++){scanf("%d%d%d",&u,&v,&w);if(w<map[u][v])map[u][v]=map[v][u]=w;}for(int i=1;i<=n;i++){scanf("%d",&pow[i]);tpow+=pow[i];}//求到每点的最短路 dij();/*  转化为DP问题   每个点为物品,路径为权值,能量为重量  求装满一半背包的最小权值和 */int r=dp();if(r==-1)printf("impossible\n");else printf("%d\n",r);}} 


 

 

原创粉丝点击