【题目描述】
给定一个 n * m [n 行 m 列] 的矩阵,现有一人位置为(i,j)[第 i 行,第 j 列] ,只能上下左右移动,给出平面上两点(x1, y1),(x2, y2),这个人每次会以最短路线从起点位置经过到达两点再返回起点,这两个点的位置坐标可以相同,请确定两点位置,使这个人所走距离最远;
【输入格式】
第一行一个数 t ,表示测试数(1 <= t <= 1e4);
接下来 t 行,每行4个数,分别代表 n,m,i,j (1 <= n, m <= 1e9, 1 <= i <= n, 1 <= j <= m);
【输出格式】
输出 t 行,每行四个数,分别代表 x1,y1,x2,y2,以空格间隔(1<= x1, x2 <=n, 1<= y1, y1 <= m);
如果有多个答案,输出一种正确的即可;
【解题思路】
1 | ||||||
ij | ||||||
2 |
(1)经分析,两点位置在(1,1)(1,m)(n, m)(n,1)中的两个时距离最大,故枚举六种可能的情况,取距离最大时点的位置即可;
分析距离时注意距离表达式,虽然可选路线很多,但距离实质相同,思路要清晰;
(2)进一步分析,发现当两点位置取对角线位置时距离一定最大,为 2 * (m - 1 + n - 1);
(3)讨论特殊情况进行代码细节优化,如 n = m = 1;
(4)n, m 数据范围为1e9,求移动距离时可能爆int,定义long long;
【正确代码】
1 #include <iostream> 2 #include <cmath> 3 4 using namespace std; 5 6 typedef long long ll; 7 8 struct pos{ 9 int x; 10 int y; 11 }p1[6], p2[6]; 12 13 int main() 14 { 15 int t, n, m, x, y, x1, y1, x2, y2; 16 scanf("%d", &t); 17 18 while(t --) 19 { 20 scanf("%d%d%d%d", &n, &m, &x, &y); 21 22 //注意结构体数组初始化方式 23 pos p1[6] = {{1, 1}, {1, 1}, {1, 1}, {1, m}, {1, m}, {n, m}}; 24 pos p2[6] = {{1, m}, {n, m}, {n, 1}, {n, m}, {n, 1}, {n, 1}}; 25 26 ll dis = 0, temp = 0; 27 28 for (int i = 0; i < 6; i ++) 29 { 30 //dis就是人到两点距离加两点间距离 31 dis = (ll)abs(p1[i].x - x) + (ll)abs(p2[i].x - x) + (ll)abs(p1[i].y - y) + (ll)abs(p2[i].y - y)+(ll)abs(p1[i].x - p2[i].x) + (ll)abs(p1[i].y - p2[i].y); 32 if(dis >= temp) 33 { 34 temp = dis; 35 x1 = p1[i].x; 36 y1 = p1[i].y; 37 x2 = p2[i].x; 38 y2 = p2[i].y; 39 } 40 } 41 printf("%d %d %d %d\n", x1, y1, x2, y2); 42 } 43 44 return 0; 45 }
【程序模拟C42】
1 pos[4] = {{1, 1},{1, m}, {n, 1}, {n, m}}; 2 for (int i = 0; i < 4; i ++) 3 for (int j = 0; j < 4; j ++) 4 { 5 6 }