鱼C论坛

 找回密码
 立即注册
查看: 2315|回复: 2

题目150:在三角形数组中搜索具有最小和的子三角形

[复制链接]
发表于 2016-8-31 23:22:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Searching a triangular array for a sub-triangle having minimum-sum

In a triangular array of positive and negative integers, we wish to find a sub-triangle such that the sum of the numbers it contains is the smallest possible.

In the example below, it can be easily verified that the marked triangle satisfies this condition having a sum of −42.

QQ20160831-1@2x.png


We wish to make such a triangular array with one thousand rows, so we generate 500500 pseudo-random numbers sk in the range ±219, using a type of random number generator (known as a Linear Congruential Generator) as follows:

t := 0
for k = 1 up to k = 500500:
    t := (615949*t + 797807) modulo 220
    sk := t−219

Thus: s1 = 273519, s2 = −153582, s3 = 450905 etc

Our triangular array is then formed using the pseudo-random numbers thus:

s1
s2  s3
s4  s5  s6  
s7  s8  s9  s10
...

Sub-triangles can start at any element of the array and extend down as far as we like (taking-in the two elements directly below it from the next row, the three elements directly below from the row after that, and so on).
The "sum of a sub-triangle" is defined as the sum of all the elements it contains.
Find the smallest possible sub-triangle sum.


题目:

在一个由正整数和负整数组成的三角形数组中,我们希望找到一个子三角形,使得该三角形中包含的所有数字之和最小。

在下图的例子中,可以验证红色标记的三角形满足上述条件,其和为 -42。

QQ20160831-1@2x.png


我们希望构造一个一千行的三角形数组,所以我们用如下一种名为线性同余法的随机数生成法生成 500500 个伪随机数 sk,范围在正负 219 之间:

t := 0
for k = 1 up to k = 500500:
t := (615949*t + 797807) modulo 220
sk := t−219

因此: s1 = 273519, s2 = −153582, s3 = 450905 等等。

因此我们用随机数组成的三角型数组具有如下形式:

s1
s2 s3
s4 s5 s6
s7 s8 s9 s10
...

子三角形可以从数组中的任意元素开始,可以向下任意延伸(从下一行取两个元素,再下一行取三个元素,如此继续)。

定义“子三角形和”为子三角形内包含的所有元素之和。

求最小的子三角形和。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2017-7-28 16:22:03 | 显示全部楼层
  1. from numba import jit
  2. import numpy as np
  3. @jit
  4. def gen_s():
  5.         s = np.zeros((1000,1000), dtype='int64')
  6.         t = 0
  7.         for l in range(1000):
  8.                 i = 0
  9.                 while i <= l:
  10.                         t = (615949*t+797807) % 2**20
  11.                         s[l,i] = t-2**19
  12.                         i += 1
  13.         return s
  14. @jit
  15. def get_sum(s, start_row, start_col, lines):
  16.         total = s[start_row, start_col]
  17.         for l in range(1, lines):
  18.                 for i in range(l+1):
  19.                         total += s[start_row+l, start_col+i]
  20.         return total
  21. @jit
  22. def solve():
  23.         s = gen_s()
  24.         smallest = 99999999
  25.         for lines in range(1000,1,-1):
  26.                 x, y = 0, 0
  27.                 while  x + lines <= 1000:
  28.                         y = 0
  29.                         while y <= x:
  30.                                 smallest = min(smallest, get_sum(s, x, y, lines))
  31.                                 y += 1
  32.                         x += 1
  33.         return smallest
  34. print(solve())
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-9-5 08:54:32 | 显示全部楼层
本帖最后由 gunjang 于 2017-9-7 16:39 编辑

继续采用pascal代码,d7编译通过,运行时间1~2s左右
  1. program p150_2;

  2. {$APPTYPE CONSOLE}

  3. uses
  4.   SysUtils, Types, Windows, Math;
  5. const
  6.   maxline = 1000;
  7.   B220 = 1 shl 20;
  8.   B219 = 1 shl 19;
  9. type
  10.   tline = array of Int64;
  11.   Ttriangle = array[0..maxline - 1] of tline;
  12.     //have n*(n+1)*(n+2)/6 triangle == 1.67billion
  13. var
  14.   triangle: Ttriangle;
  15.   sumtriangle: Ttriangle;
  16.   minsum: int64; //2^12 * 50w may >= 2^32
  17.   st: DWORD;

  18. procedure initSK;
  19. var
  20.   t, s: int64;
  21.   line, col: integer;
  22. begin
  23.   minsum := 0;
  24.   t := 0;
  25.   for line := 0 to maxline - 1 do
  26.   begin
  27.     setlength(triangle[line], line + 1);
  28.     for col := 0 to line do
  29.     begin
  30.       t := (615949 * t + 797807) mod B220;
  31.       s := t - b219;
  32.       triangle[line][col] := s;
  33.       if s < minsum then
  34.         minsum := s; //sidelength=1
  35.     end;
  36.   end;
  37. end;

  38. procedure calSumofTriangles;
  39. var
  40.   x, y: integer;
  41.   sidelength: integer;
  42.   x2, y2: integer;
  43.   bottomsum: int64;
  44. begin
  45.   //calculate sidelength=2 Triangles
  46.   for y := 0 to maxline - 2 do
  47.   begin
  48.     setlength(sumtriangle[y], y + 1);
  49.     for x := 0 to y do
  50.     begin
  51.       sumtriangle[y][x] := triangle[y][x] + triangle[y + 1][x] + triangle[y + 1][x + 1];
  52.       if sumtriangle[y][x] < minsum then
  53.         minsum := sumtriangle[y][x];
  54.     end;
  55.   end;

  56.   for sidelength := 3 to maxline do
  57.   begin
  58.     for y := 0 to maxline - sidelength do
  59.     begin
  60.       bottomsum := 0;
  61.       y2 := y + sidelength - 1;
  62.       for x2 := 0 to sidelength - 1 do
  63.         inc(bottomsum, triangle[y2][x2]);
  64.       inc(sumtriangle[y][0], bottomsum);
  65.       if sumtriangle[y][0] < minsum then
  66.         minsum := sumtriangle[y][0];

  67.       for x := 1 to y do
  68.       begin
  69.         inc(bottomsum, -triangle[y2][x - 1] + triangle[y2][x - 1 + sidelength]);
  70.         sumtriangle[y][x] := sumtriangle[y][x] + bottomsum;
  71.         if sumtriangle[y][x] < minsum then
  72.           minsum := sumtriangle[y][x];
  73.       end;
  74.     end;

  75.     if sidelength mod 50 = 0 then
  76.       writeln(Format('sidelenght=%d, minSum=%d', [sidelength, minsum]));
  77.   end;
  78. end;

  79. begin
  80.   st := gettickcount;
  81.   initSK;
  82.   calSumofTriangles;
  83.   writeln(minsum); //-271248680
  84.   writeln(Format('cost %n s', [(gettickcount - st) / 1000])); //1.56s-2.36s
  85.   readln;
  86. end.
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-20 02:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表