程序控

IPPP (Institute of Penniless Peasent-Programmer) Fellow

:: :: :: :: :: :: :: ::
 77 随笔 :: 0 文章 :: 457 评论 :: 0 引用

Time limit: 3.000 seconds

Background背景

Graph algorithms form a very important part of computer science and have a lineage that goes back at least to Euler and the famous Seven Bridges of Königsberg problem. Many optimization problems involve determining efficient methods for reasoning about graphs.

This problem involves determining a route for a postal worker so that all mail is delivered while the postal worker walks a minimal distance, so as to rest weary legs.

The Problem问题

Given a sequence of streets (connecting given intersections) you are to write a program that determines the minimal cost tour that traverses every street at least once. The tour must begin and end at the same intersection.

The "real-life" analogy concerns a postal worker who parks a truck at an intersection and then walks all streets on the postal delivery route (delivering mail) and returns to the truck to continue with the next route.

The cost of traversing a street is a function of the length of the street (there is a cost associated with delivering mail to houses and with walking even if no delivery occurs).

In this problem the number of streets that meet at a given intersection is called the degree of the intersection. There will be at most two intersections with odd degree. All other intersections will have even degree, i.e., an even number of streets meeting at that intersection.

The Input输入

The input consists of a sequence of one or more postal routes. A route is composed of a sequence of street names (strings), one per line, and is terminated by the string "deadend" which is NOT part of the route. The first and last letters of each street name specify the two intersections for that street, the length of the street name indicates the cost of traversing the street. All street names will consist of lowercase alphabetic characters.

For example, the name foo indicates a street with intersections f and o of length 3, and the name computer indicates a street with intersections c and r of length 8. No street name will have the same first and last letter and there will be at most one street directly connecting any two intersections. As specified, the number of intersections with odd degree in a postal route will be at most two. In each postal route there will be a path between all intersections, i.e., the intersections are connected.

The Output输出

For each postal route the output should consist of the cost of the minimal tour that visits all streets at least once. The minimal tour costs should be output in the order corresponding to the input postal routes.

one
two
three
mit
dartmouth
tasmania
york
emory
cornell
duke
kaunas
hildesheim
concord
arkansas
williams
glasgow

11
114

Solution解答

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
//主函数
int main(void) {
//aMat为连通路口的邻接矩阵，aIdHash为路口字母与其编号的对应表
//nNodeCnt为路口数量，nRout为最小路径长度
int aMat[26][26], aIdHash[26], nNodeCnt = 0, nRout = 0, nInf = 0xFFFFFF;
fill(&aMat[0][0], &aMat[26][0], nInf);
fill(&aIdHash[0], &aIdHash[26], nInf);
//循环处理每一行输入，结束时将nRout清0
for (string strName; cin >> strName;) {
//如果街名为结束符，则按前一阶段的输入数据进行运算
//aOdd数组用于记录奇顶点，pOdd是aOdd的指针形式
int aOdd[2] = {0, 0}, *pOdd = &aOdd[0];
for (int i = 0; i < nNodeCnt && pOdd != &aOdd[2]; ++i) {
//统计每一个顶点的相邻顶点数(连通路口数)
for (int j = 0; j < nNodeCnt; *pOdd += (aMat[i][j++] != nInf));
//如果发现奇顶点，加入奇顶点数组
if (*pOdd % 2 != 0) {
*(pOdd++) = i;
}
}
//如果存在两个奇顶点，则开始Floyd算法，找最短路径
if (pOdd != aOdd) {
for (int k = 0, nSum; k < nNodeCnt; ++k) {
for (int i = 0; i < nNodeCnt; ++i) {
//为加快运算减少代码，设置临时变量p = aMat[i]
for (int j = 0, *p = &aMat[i][0]; j < nNodeCnt; ++j) {
nSum = p[k] + aMat[k][j];
p[j] = nSum < p[j] ? nSum : p[j];
}
}
}
nRout += aMat[aOdd[0]][aOdd[1]];
}
//输出最小路径长度
cout << nRout << endl;
//初始化数据，以便进行下一轮计算
fill(&aMat[0][0], &aMat[nNodeCnt][0], nInf);
fill(&aIdHash[0], &aIdHash[26], nInf);
nRout = nNodeCnt = 0;
continue;
}
//街道名称的首尾字母
int nF = *strName.begin() - 'a', nL = *(strName.end() - 1) - 'a';
//验证路口字母是否已经存在，否则添加路口
nF = (aIdHash[nF] = aIdHash[nF] == nInf ? nNodeCnt++ : aIdHash[nF]);
nL = (aIdHash[nL] = aIdHash[nL] == nInf ? nNodeCnt++ : aIdHash[nL]);
//在邻接距阵中添加路口节点
aMat[nF][nL] = aMat[nL][nF] = strName.length();
//统计路径长度
nRout += strName.length();
}
return 0;
}

posted on 2010-08-13 18:46  Devymex  阅读(2177)  评论(0编辑  收藏