鱼C论坛

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

题目149:搜索一个最大和子序列

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

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

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

x
Searching for a maximum-sum subsequence

Looking at the table below, it is easy to verify that the maximum possible sum of adjacent numbers in any direction (horizontal, vertical, diagonal or anti-diagonal) is 16 (= 8 + 7 + 1).

QQ20160831-1@2x.png


Now, let us repeat the search, but on a much larger scale:

First, generate four million pseudo-random numbers using a specific form of what is known as a "Lagged Fibonacci Generator":

For 1 ≤ k ≤ 55, sk = [100003 − 200003k + 300007k3] (modulo 1000000) − 500000.
For 56 ≤ k ≤ 4000000, sk = [sk−24 + sk−55 + 1000000] (modulo 1000000) − 500000.

Thus, s10 = −393027 and s100 = 86613.

The terms of s are then arranged in a 2000×2000 table, using the first 2000 numbers to fill the first row (sequentially), the next 2000 numbers to fill the second row, and so on.

Finally, find the greatest sum of (any number of) adjacent entries in any direction (horizontal, vertical, diagonal or anti-diagonal).


题目:

请看下面的表格,可以轻易验证:在任意方向上(水平,竖直,两个对角线)相邻数之和最大为 16(= 8 + 7 + 1)。

QQ20160831-1@2x.png


现在,在更大的规模上重复上面的搜索:

首先,用 Lagged Fibonacci Generator 的方法生成 400 万个伪随机数:

对于 1 ≤ k ≤ 55, sk = [100003 − 200003k + 300007k3] (modulo 1000000) − 500000.
对于56 ≤ k ≤ 4000000, sk = [sk−24 + sk−55 + 1000000] (modulo 1000000) − 500000.

因此, s10 = −393027 and s100 = 86613.

然后,将如此生成的 s 安放在一个 2000×2000 的表中,用前 2000 个数依次填充第一行,如此继续。

最后,求在这个表中任意方向上最大的相邻数(任意多个)之和。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-7-26 17:30:15 | 显示全部楼层
from numba import jit
import numpy as np 
@jit
def gen_s():
        s = np.zeros(4000000, dtype='int64')
        for k in range(0, 55):
                s[k] = (100003-200003*(k+1)+300007*(k+1)**3) % 1000000 - 500000
        for k in range(55, 4000000):
                s[k] = (s[k-24]+s[k-55]+1000000) % 1000000 - 500000
        return s.reshape(2000,2000)

@jit
def get_max_wd(s):
        maxsum_w = np.max(np.sum(s, axis=1))
        maxsum_d = np.max(np.sum(s, axis=0))
        maxsum = max(maxsum_d, maxsum_w)
        return maxsum

@jit
def get_max_lr(s, n):
        maxsum = 0
        for line in range(n):
                total = 0
                y = line
                x = 0
                while x<n and y<n:
                        total += s[x,y]
                        x += 1
                        y += 1
                maxsum = max(maxsum, total)
        for line in range(n-1,-1,-1):
                total = 0
                y = line
                x = n-1
                while x>=0 and y>=0:
                        total += s[x,y]
                        x -= 1
                        y -= 1
                maxsum = max(maxsum, total)
        for line in range(n-1,-1,-1):
                total = 0
                y = line
                x = 0
                while x<n and y>=0:
                        total += s[x,y]
                        x += 1
                        y -= 1
                maxsum = max(maxsum, total)
        for line in range(n):
                total = 0
                y = line
                x = n-1
                while x>=0 and y<n:
                        total += s[x,y]
                        x -= 1
                        y += 1
                maxsum = max(maxsum, total)
        return maxsum

@jit
def solve():
        s = gen_s()
        return max(get_max_wd(s), get_max_lr(s, 2000))

print(solve())

速度应该是够了,算法还有些问题,下次再检查。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-7-28 15:15:07 | 显示全部楼层
用4x4的矩形验算都是正确的,大的矩形第10个和第100个数值也都是正确的,不知道错哪了。。。
from numba import jit
import numpy as np 
@jit
def gen_s():
        s = np.zeros(4000000, dtype='int64')
        for k in range(0, 55):
                s[k] = (100003-200003*(k+1)+300007*(k+1)**3) % 1000000 - 500000
        for k in range(55, 4000000):
                s[k] = (s[k-24]+s[k-55]+1000000) % 1000000 - 500000
        return s.reshape(2000,2000)

@jit
def get_max_w(s):
        return np.max(np.sum(s, axis=1))

@jit
def get_max_d(s):
        return np.max(np.sum(s, axis=0))

@jit
def get_max_l(s, n):
        maxsum = 0
        for line in range(n):
                total = 0
                y = line
                x = 0
                while x<n and y<n:
                        total += s[x,y]
                        x += 1
                        y += 1
                maxsum = max(maxsum, total)
        for line in range(n-1,-1,-1):
                total = 0
                y = line
                x = n-1
                while x>=0 and y>=0:
                        total += s[x,y]
                        x -= 1
                        y -= 1
                maxsum = max(maxsum, total)
        return maxsum

@jit
def get_max_r(s, n):
        maxsum = 0
        for line in range(n-1,-1,-1):
                total = 0
                y = line
                x = 0
                while x<n and y>=0:
                        total += s[x,y]
                        x += 1
                        y -= 1
                maxsum = max(maxsum, total)
        for line in range(n):
                total = 0
                y = line
                x = n-1
                while x>=0 and y<n:
                        total += s[x,y]
                        x -= 1
                        y += 1
                maxsum = max(maxsum, total)
        return maxsum

@jit
def solve():
        s = gen_s()
        return get_max_d(s),get_max_w(s),get_max_l(s, 2000),get_max_r(s, 2000)

print(solve())

(48519449, 44540336, 43117448, 40358088)
[Finished in 2.8s]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-22 21:55

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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