zju1037-Gridland(解题来自《ACM国际大学生程序设计竞赛题解(1)》
【题目大意】
背景:
多年来,计算机科学家一直在寻找有效的方法来解决困难的计算机问题。有些问题已经找到了有效的算法,如排序、计算多边形面积、寻找图的最短路径,这些都是“容易的”问题。而“困难的”问题,目前只有计算时间是指数级的算法,旅行售货员的问题就是其中之一。给出N个城市,及城市之间的道路,问题是寻找一条最短的路径,让售货员访问每一个城市一次且只有一次,又回到出发点。
问题:
Gridland的总统雇佣你来编写一个程序,计算在这个国家中所有城市的旅行售货员问题的最短长度。在Gridland,每个城市都位于矩形网格的一个点上。通向每个城市的道路只有东、西、南、北、东南、东北、西南和西北方向,在每个方向上只有一个相邻的城市。东西、南北方向的长度为1,长度单位是欧几里得距离。如图(图略)所示是一个2*3的Gridland,最短的环游路线长度是6。
输入:
第一行是测试列数。
每个测试例,在一行里有两个整数m和n(1<m,n<50),中间有一个空格,是二维栅格的大小。
输出:
对每个测试例,第一行输出:“Scenario #i:",i是从1开始的测试例编号。第二行输出售货员环游问题的最短长度,精确到两位小数。每个测试例之后又一个空行。
【算法分析】
题目中一直强调旅行售货员问题,容易诱导竞赛者去使用复杂的算法,如回溯算法、分支限定算法。而本题的城市位置是特殊的,边长也是特殊的,所以能够寻找简单的规律进行计算。
网友Winsty给出了一个简捷的算法,当m或n为偶数时,最短长度为mn;当m和n同时为技术时,最短路长度为mn再加0.41,因为要走一个斜边。图略。
代码如下:
#include <iostream> #include <cstdio> using namespace std; int main() { int n; int i=1; scanf("%d",&n); while(n--) { int a,b; scanf("%d%d",&a,&b); printf("Scenario #%d:\n",i++); printf("%d",a*b); if(a%2&&b%2) printf(".41"); else printf(".00"); printf("\n\n"); } return 0; }