题目描述
冬天到了,小伙伴们都懒得出去吃饭了,纷纷打电话叫起了外卖。送外卖的小哥想找出一条最短的路径,小区门口进来,送完外卖又回到小区门口。
整个小区是一个由m*n个边长为1的正方形组成的矩形,各幢公寓楼分布于正方型的顶点上,小区门口位于左上角。每幢楼与相邻的八个方向的楼之间都有道路。
下图为m=2,n=3的小区地图,并且外卖小哥要经过的最短路径为6。
输入描述:
输入有多组数据。
每组数据包含两个整数m (2≤n≤2128) 和n (2≤r≤2128),分别代表行数和列数。
输出描述:
对应每一组数据,输出外卖小哥需要经过的最短路径。结果保留两位小数。
输入例子:
2 2
3 3
输出例子:
4.00
9.41
这道题问的是让你找出访问所有楼栋需要的最短路径。
下面是评论区找出的结论。
这个结论还是比较难想到的,尤其是证明它为最优路径。
由于输入整数m (2≤n≤2128) 和n (2≤r≤2128)范围非常大,因此我们需要手动写一个大数乘法器。没办法,C艹库少。。。
我采用的是万进制
,逢万进一
。
输入的是数值字符串,比如"12345601230009
",然后转换成int数组intsNum[4, 9, 123, 3456, 12]
,intsNum[0]
表示数组的长度,intsNum[1]=9
表示数值字符串中的第一段“0999”,intsNum[2]=123
,表示数组中的第二段0123
,intsNum[3]=3456
,表示数组中的第三段3456
,intsNum[4]=12
,表示数组中的第四段12
#include <iostream>
#include <string.h>
#include <string>
using namespace std;
//将两个数组相乘,并且结果存放子啊num3
//数组示例[4,123,0,1234,9],4表示长度,真正表示是的值为 ‘9 1234 0000 0123’
void bigNumMutli(int* num1, int* num2, int* num3, int maxLen) {
memset(num3, 0, maxLen);
//1、对num1、num2进行相乘
for (int i = 1; i <= num2[0]; ++i) {
for (int j = 1; j <= num1[0]; ++j) {
//num1的第j位 与 num2的第i位相乘,应该放在num3的 第i + j - 1位上,画一个多位数相乘算术式可知
num3[i + j - 1] += num1[i] * num2[j];
if (num3[i + j - 1] > 9999) {
//num3[i + j - 1] 逢万进位
num3[i + j] += num3[i + j - 1] / 10000;
num3[i + j - 1] %= 10000;
}
}
}
//2、检查num3是否有进位,注意长度为m、n位的两个数相乘结果长度不会超过 m + n
//初始化num3的长度为 num1、num2之和
num3[0] = num1[0] + num2[0];
for (int i = 1; i < num3[0]; ++i) {
if (num3[i] > 10000) {
num3[i + 1] += num3[i] / 10000;
num3[i] %= 10000;
}
}
//如果最高位为0,说明结果小于
if (num3[num3[0]] == 0) {
num3[0] -= 1;
}
}
//将数字字符串转成int数组,比如"12304560001",转换结果为[3, 1, 456, 123]
void strToInts(string num, int* numInts, int maxLen) {
memset(numInts, 0, maxLen);
for (int i = (int)num.size() - 1; i >= 0; ) {
int tempNum = 0, j = 0, weight = 1;
//取出四位转成整形
while (i >= 0 && j++ < 4) {
tempNum += (num[i--] - '0') * weight;
weight *= 10;
}
numInts[++numInts[0]] = tempNum;
}
}
//将int数组转换会字符串类型
string intsToStr(int* numInts) {
if (numInts[0] == 0) {
return "0";
}
//最高位不需要补零
string resStr = to_string(numInts[numInts[0]]);
//注意访问顺序,是从高->低
for (int i = numInts[0] - 1; i >= 1; --i) {
string tempStr = "";
//中间不足四位需要补零
if (numInts[i] < 1000) {
tempStr += '0';
}
if (numInts[i] < 100) {
tempStr += '0';
}
if (numInts[i] < 10) {
tempStr += '0';
}
tempStr += to_string(numInts[i]);
resStr.append(tempStr);
}
return resStr;
}
string mutli(string num1, string num2) {
int intsNum1[101] = { 0 }, intsNum2[101] = { 0 }, intsSum[101] = { 0 };
strToInts(num1, intsNum1, 101);
strToInts(num2, intsNum2, 101);
bigNumMutli(intsNum1, intsNum2, intsSum, 101);
return intsToStr(intsSum);
}
int main() {
string a, b;
//scanf返回值为正确输入数据的变量个数,当一个变量都没有成功获取数据时,此时返回-1
while (cin >> a >> b) {
string tempRes = mutli(a, b);
if ((a[a.size() - 1] - '0') % 2 == 0 || (b[b.size() - 1] - '0') % 2 == 0) {
tempRes += ".00";
} else {
//注意:√2 - 1 = 0.41
tempRes += ".41";
}
cout << tempRes << endl;
}
return 0;
}