眨眼培训就过了大半喽。我还是很喜欢的。。。
上午做了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搞定的呀。