http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=37
思路:
由于边长采用欧几里得距离,所以从一个点出发到其斜线方向的邻点的距离为Sqrt(2)个单位。
显然,要使总长度最短,那么路过的斜线越少越好。
也就是说,在迫不得已的时候,永远都不要去选择斜线路径。(结论一)
(由于除了起点,每个点都要过一次,且只能过一次,那么就可能存在某些情况不得不走斜线)
由于在遍历所有点之后要回到起点,那么对于整个路径的前进方向来说,
(如果不走斜线)某一个方向的前进次数必须和其反方向的次数相等。(结论二)
那么,如果m和n均为奇数的时候,结论二是不会被满足的。
也就是说,在m和n均为奇数的时候,会迫不得已选择斜线。
而当m和n至少有一个偶数的时候,能轻松找到一种行进方法,在不走斜线的前提下完成任务。(结论三)
结论三包含着2个信息:
1 字面意思;
2 如果m和n均为奇数的时候,某方向及其反方向的行进次数的差值不会大于1。
根据第二点可以进一步得知,所选路径中至多选一个斜线路径。
综上所述,
当两者至少有一个偶数的时候,最短路径就是m*n;
否则,m*n-1+sqrt(2) = m*n+0.41。
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int m,n,loop;
float len = 0;
int count = 1;
cin >> loop;
for(;loop > 0;loop--) {
cin >> m >>n;
if(m < 2 || m > 50) break;
if(n < 2 || n > 50) break;
if(m % 2 == 0 || n % 2 == 0) {
len = m * n;
} else {
len = m * n + 0.41;
}
cout << "Scenario #" << count++ << ":" << endl
<< setiosflags(ios::fixed) << setprecision(2)
<< len << endl << endl;
}
return 0;
}