眨眼培训就过了大半喽。我还是很喜欢的。。。
上午做了HDU2112
还是求最短路径的,不同的是这题没有直接给地点标号,需要我们来处理。
这题要注意一下集中情况:
1、start、end地点在下面的路径中不一点会出现,所以在标号时需要对这两个点也处理。
2、无向图的处理可能会增加时间复杂度,但不会改变最短路径的长度,因为除非是负权边,
否则a->b被处理过,b->a一点不会被处理了。
3、这题的建图。利用temp[][]表将地点不重复地存储起来,建立地点和数字标号间的唯一对应
关系。然后在查找建图。
4、SPFA算法,不仅仅可以求出最短路径,还可以判断两点是否连通。(有向图、无向图均可)
代码:
#include<iostream> #include<vector> #include<queue> using namespace std; const int maxRoad=10001; //路径数 const int maxSize=151; //地点数 const int maxLen=31; //地点的最大长度 const int INF=0x7fffffff; struct node //边 { char start[maxLen]; char end[maxLen]; int from; int to; int cost; }edge[maxRoad]; int minPath[maxSize]; //最短路 bool inQ[maxSize]; //是否在队列中 int numEdge,numAdress,from,to; //路径数、点数、起点、终点 char start[maxLen],end[maxLen]; char temp[maxSize][maxLen]; //不重复存放地存放每个点 vector<node> myV[maxSize]; //连接表 int findIndex(char c[]) //找地点的标示 { for(int i=0;i<numAdress;i++) { if(strcmp(c,temp[i])==0) { return i; } } return -1; } void input() { numAdress=0; getchar(); scanf("%s%s",&start,&end); //如果不在temp[][]表中就放进去 if(findIndex(start)==-1) strcpy(temp[numAdress++],start); if(findIndex(end)==-1) strcpy(temp[numAdress++],end); for(int i=0;i<numEdge;i++) { getchar(); scanf("%s%s%d",&edge[i].start,&edge[i].end,&edge[i].cost); if(findIndex(edge[i].start)==-1) strcpy(temp[numAdress++],edge[i].start); if(findIndex(edge[i].end)==-1) strcpy(temp[numAdress++],edge[i].end); } } void buildMap() { for(int j=0;j<maxSize;j++) { myV[j].clear(); } from=findIndex(start); to=findIndex(end); for(int i=0;i<numEdge;i++) { //建立无向图 edge[i].from=findIndex(edge[i].start); edge[i].to=findIndex(edge[i].end); myV[edge[i].from].push_back(edge[i]); edge[i].to=findIndex(edge[i].start); edge[i].from=findIndex(edge[i].end); myV[edge[i].from].push_back(edge[i]); } } void SPFA() { for(int i=0;i<maxSize;i++) minPath[i]=INF; minPath[from]=0; memset(inQ,false,sizeof(inQ)); inQ[from]=true; queue<int> myQ; myQ.push(from); while(!myQ.empty()) { int from,to,cost; from=myQ.front(); myQ.pop(); for(int j=0;j<myV[from].size();j++) { to=myV[from][j].to; cost=myV[from][j].cost+minPath[from]; if(cost<minPath[to]) { minPath[to]=cost; if(!inQ[to]) { inQ[to]=true; myQ.push(to); } } } inQ[from]=false; } if(minPath[to]!=INF) printf("%d\n",minPath[to]); else printf("-1\n"); } int main() { while(scanf("%d",&numEdge)==1,numEdge!=-1) { if(numEdge==0) { getchar(); scanf("%s%s",&start,&end); if(strcmp(start,end)==0) printf("0\n"); else printf("-1\n"); continue; } input(); buildMap(); SPFA(); } system("pause"); return 0; }
然后下午和晚上就一直在做HDU1385了。
可是还没搞定呢。。。
这题不仅要求解最短路径,还要计算节点处费用。不仅如此,还要把路径打印出来。
更坑爹的是,如果有多条最短路径,只打印按字母表排序最小的。。。
一直WA,各种不解,最不解的是网上有些代码明明不对,依旧A了。。。
(打印最短路径,大家可以到这里看看:SPFA最短路径
就把我的WA代码贴下:
#include<iostream> #include<vector> #include<queue> #include<stack> #include<cstring> using namespace std; const int maxn=1001; const int INF=0x7fffffff; struct edge { int to; int cost; }; int mat[maxn][maxn]; int waste[maxn]; int sourceFirst[maxn]; vector<edge> myV[maxn]; //利用临界表存储图 int numNode; //点数 int minPath[maxn]; //最短路 int start,end; //起点、终点 bool inQ[maxn]; //是否入队 void inputItial() { int i,j; for(i=1;i<=numNode;i++) //输入距离矩阵 { for(j=1;j<=numNode;j++) { scanf("%d",&mat[i][j]); } } for(i=1;i<=numNode;i++) //输入中转站的费用 { scanf("%d",&waste[i]); } for(i=0;i<maxn;i++) //清空再使用 { myV[i].clear(); } for(i=1;i<=numNode;i++) //建图 { for(j=1;j<=numNode;j++) { if(i==j || mat[i][j]==-1) continue; edge e; e.cost=mat[i][j]+waste[i]; e.to=j; myV[i].push_back(e); } } } void output(int start,int end) { printf("From %d to %d :\n",end,start); printf("Path: %d",end); while(sourceFirst[end]!=0) { printf("-->%d",sourceFirst[end]); end=sourceFirst[end]; } printf("\n"); } void SPFA(int start,int end) //最短路径快速算法 Shortest Path Faster Algorithm { memset(inQ,false,sizeof(inQ)); inQ[start]=true; for(int j=0;j<maxn;j++) minPath[j]=INF; minPath[start]=0; queue<int> myQ; myQ.push(start); int now,to,cost; while(!myQ.empty()) { now=myQ.front(); myQ.pop(); sourceFirst[start]=0; for(int k=0;k<myV[now].size();k++) { to=myV[now][k].to; cost=myV[now][k].cost+minPath[now]; if(minPath[to]>cost) { sourceFirst[to]=now; //记录下to的来源为now minPath[to]=cost; if(!inQ[to]) { inQ[to]=true; myQ.push(to); } } else if(minPath[to]==cost) { if(now<sourceFirst[to]) { sourceFirst[to]=now; } } } inQ[now]=false; } if(start==end) { printf("From %d to %d : \n",start,end); printf("Path: %d\n",start); printf("Total cost : 0\n\n"); } else { output(start,end); printf("Total cost : %d\n\n",minPath[end]-waste[start]); } } int main() { while(scanf("%d",&numNode)==1,numNode) { inputItial(); while(scanf("%d%d",&start,&end)==2,start!=-1&&end!=-1) { SPFA(end,start); } } system("pause"); return 0; }
通过上次的比赛,我觉得做题还是得扎实。
做了一题完全可以给自己加点难度。什么数据范围搞大点、输出格式严格点、
时间放短点。。。
这样可以引导自己更深入的思考问题,个人觉得可能比你一直做模板题,浑浑噩噩的效果
会好点的。这也是我给自己提的要求。所以,我一定要把HDU1385搞定的呀。