[problem11]欧拉
In the 20×20 grid below, four numbers along a diagonal line have been marked in red.
08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48
The product of these numbers is 26 × 63 × 78 × 14 = 1788696.
What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 20×20 grid?
思路:
1)从包含所有数字的长字符串中解析出20*20的int数组;
2)对得到的int数组,逐个取出元素,
求出其各个方向的4个数的乘积并计算出max。
我的实现:
View Code #include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string fullString("08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00\
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65\
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91\
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80\
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50\
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70\
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21\
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72\
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95\
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92\
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57\
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58\
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40\
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66\
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69\
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36\
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16\
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54\
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48");
int a[20][20];
string::size_type index = 0;
size_t cntChars = fullString.length();
int i = 0;
int j = 0;
string testString = fullString;
string::size_type curIndex = 0;
while(curIndex != -1)
{
testString = testString.erase(0, testString.find_first_not_of(' '));
curIndex = testString.find_first_of(' ');
if(curIndex >= 0)
{
string substr = testString.substr(0, curIndex);
if(j <= 19)
{
a[i][j] = atoi(substr.c_str());
j++;
}
else
{
// next row.
j = 0;
i++;
if(i <= 19)
a[i][j++] = atoi(substr.c_str());
}
testString = testString.substr(curIndex+1);
}
}
int max = 0;
for(int i = 0; i < 20; i++)
{
for(int j = 0; j < 20; j++)
{
//up,down,left,right,diagonal (include 4 directions!!)
int product = 0;
if(i-3>=0) // up.
{
product = a[i][j]*a[i-1][j]*a[i-2][j]*a[i-3][j];
if(product > max)
{
max = product;
}
}
if(i+3<=19) // down.
{
product = a[i][j]*a[i+1][j]*a[i+2][j]*a[i+3][j];
if(product > max)
{
max = product;
}
}
if(j-3>=0) // left
{
product = a[i][j]*a[i][j-1]*a[i][j-2]*a[i][j-3];
if(product > max)
{
max = product;
}
}
if(j+3<=19) // right.
{
product = a[i][j]*a[i][j+1]*a[i][j+2]*a[i][j+3];
if(product > max)
{
max = product;
}
}
if(i+3 <= 19 && j+3 <= 19) // right-down diagonal
{
product = a[i][j]*a[i+1][j+1]*a[i+2][j+2]*a[i+3][j+3];
if(product > max)
{
max = product;
}
}
if(i-3 >= 0 && j-3 >= 0) // left-up diagonal
{
product = a[i][j]*a[i-1][j-1]*a[i-2][j-2]*a[i-3][j-3];
if(product > max)
{
max = product;
}
}
if(i-3 >= 0 && j+3 <= 19) // right-up diagonal
{
product = a[i-1][j+1]*a[i-2][j+2]*a[i-3][j+3]*a[i][j];
if(product > max)
{
max = product;
}
}
if(i+3 <= 19 && j-3 >= 0) // left-down diagonal
{
product = a[i][j]*a[i+1][j-1]*a[i+2][j-2]*a[i+3][j-3];
if(product > max)
{
max = product;
}
}
}
}
cout << max << endl;
return 0;
}
学到的:
1)起初考虑算法时,少考虑了两个对角线的乘积,导致结果错误。再有,使用STL string时,有点生疏了,当然他的string功能也实在太弱,连一个string的split都要自己实现。
2)虽然我的算法不存在performance问题,但存在重复计算。仔细考虑后,发现考虑需要计算方向的规则很清晰:如果这个方向涉及当前元素的next row/column的元素,计算它;如果这个方向涉及当前元素的former row/column的元素,the former element应该已经把那些方向计算过了,所以可以安全跳过。需要计算的方向有4个:right, down, right-down, left-down。见下面的改进后的算法(由于数组规模不大,所以spentime没有啥变化):
View Code #include <string>
#include <ctime>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
clock_t startTime = clock();
string fullString("08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08\
49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00\
81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65\
52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91\
22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80\
24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50\
32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70\
67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21\
24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72\
21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95\
78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92\
16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57\
86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58\
19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40\
04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66\
88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69\
04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36\
20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16\
20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54\
01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48");
int a[20][20];
string::size_type index = 0;
size_t cntChars = fullString.length();
int i = 0;
int j = 0;
string testString = fullString;
string::size_type curIndex = 0;
while(curIndex != -1)
{
testString = testString.erase(0, testString.find_first_not_of(' '));
curIndex = testString.find_first_of(' ');
if(curIndex >= 0)
{
string substr = testString.substr(0, curIndex);
if(j <= 19)
{
a[i][j] = atoi(substr.c_str());
j++;
}
else
{
// next row.
j = 0;
i++;
if(i <= 19)
a[i][j++] = atoi(substr.c_str());
}
testString = testString.substr(curIndex+1);
}
}
int max = 0;
for(int i = 0; i < 20; i++)
{
for(int j = 0; j < 20; j++)
{
// All directions should include: up,down,left,right,diagonal (include 4 directions!!). but considering reducing duplicate calculations,
// some directions can be skipped. The basic rule is: for an element, the directions including its next elements (next row, next column)
// should be calculated while those including its former elements (former row, former column) can be skipped safely as its former elements
// should already do calculations for its "next" directions.
int product = 0;
if(i+3<=19) // down.
{
product = a[i][j]*a[i+1][j]*a[i+2][j]*a[i+3][j];
if(product > max)
{
max = product;
}
}
if(j+3<=19) // right.
{
product = a[i][j]*a[i][j+1]*a[i][j+2]*a[i][j+3];
if(product > max)
{
max = product;
}
}
if(i+3 <= 19 && j+3 <= 19) // right-down diagonal
{
product = a[i][j]*a[i+1][j+1]*a[i+2][j+2]*a[i+3][j+3];
if(product > max)
{
max = product;
}
}
if(i+3 <= 19 && j-3 >= 0) // left-down diagonal
{
product = a[i][j]*a[i+1][j-1]*a[i+2][j-2]*a[i+3][j-3];
if(product > max)
{
max = product;
}
}
//if(j-3>=0) // left
//{
// product = a[i][j]*a[i][j-1]*a[i][j-2]*a[i][j-3];
// if(product > max)
// {
// max = product;
// }
//}
//if(i-3>=0) // up.
//{
// product = a[i][j]*a[i-1][j]*a[i-2][j]*a[i-3][j];
// if(product > max)
// {
// max = product;
// }
//}
//if(i-3 >= 0 && j-3 >= 0) // left-up diagonal
//{
// product = a[i][j]*a[i-1][j-1]*a[i-2][j-2]*a[i-3][j-3];
// if(product > max)
// {
// max = product;
// }
//}
//if(i-3 >= 0 && j+3 <= 19) // right-up diagonal
//{
// product = a[i-1][j+1]*a[i-2][j+2]*a[i-3][j+3]*a[i][j];
// if(product > max)
// {
// max = product;
// }
//}
}
}
cout << "max:" << max << endl;
clock_t endTime = clock();
double spentTime = difftime(endTime, startTime);
cout << "spentTime:" << spentTime << endl;
return 0;
}


浙公网安备 33010602011771号