Aikilis' Blog

Mathematics, Computer Science and puzzles.

二月 6th, 2012

四面体体积的类海伦公式

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.2.6

海伦公式吧是一个非常实用的公式。通过三角形的三边长度,就能够算出三角形的面积。

海伦公式又称作“海伦-秦九韶”公式,定义如下:

S = sqrt(p * (p – a) * (p – b) * (p – c))

其中p为三角形半周长:p = (a + b + c) / 2。

我们知道,几何的性质通常是可以推广的,海伦公式在三维空间中,也有其优雅的性质。通过给出四面体的6条边长,我们可以计算出四面体的体积。请尝试推导三维的海伦公式。

题解:

三维海伦公式又称为欧拉的四面体问题。

欧拉的四面体问题

历史上欧拉(Euler)提出了这样一个问题:如何用四面体的六条棱长去表示它的体积
这个问题可以用矢量代数的基本知识来解决,下面是解答过程.

clip_image001

建立如图16÷所示坐标系,设A、B、C三点的坐标分别为(a1,b1,c1)、(a2,b2,c2)和(a3,b3,c3),并设四面体0一Abc的六菜棱长分别为l、m,n,p,q,r.由立体几何知道,该四面体的体积v等于以矢量clip_image002为棱的平行六面体的体积(记作v6)的clip_image003,而由空间解析几何可知, 组成右手系时,以它们为棱的平行六面体的体积
clip_image004
于是得
clip_image005
由于行列式转置后其值不变,将第二个行列式进行转置后再相乘,得
clip_image006
根据矢量的数量积的坐标表示,有
clip_image007
由矢量的数量积定义,又有

clip_image008
将以上各式代入(1),得
clip_image009 (2)
这就是欧拉的四面体求积公式
例:一块形状为四面体的花岗岩巨石,量得六条棱长分别为
l=10米,m=15米,n=12米
p=14米,q=13米,r=11米
clip_image010

即花岗岩巨石的体积约为clip_image011. 古埃及的金字塔形状为四面体,因而可通过测量其六条棱长去计算金字塔的体积。

这是解析几何的解决方案,实际上还有一个古典几何的公式[1],但是其中不仅需要棱长,还需要角度,不过形式更加优美。

参考文献:

[1]欧培辅,李长禄:类似于海伦公式的四面体体积公式.

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 6th, 2012

趣题:少了那一块到哪里去了?

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.2.5

201202051127141a05be6867d47e4bc80d88caea2d5dbf

题解:

其实也是个障眼法,

   我们来算算面积

   图一 :  红色:8 * 3 / 2 = 12

                  青色:5 * 2 / 2 = 5

                  黄色:7

                  绿色:8 

                  一共:12 + 5 + 7 + 8 = 32

    可是!如果你是:13(三角形看成一个整体13为它的底) * 5(整体的高) / 2 =32.5 > 32???

    这是为啥呢?

    其实道理很简单:原因就在红色三角形和青色三角形,他们的斜边不在一条直线上,也就是说这个组装的三角形比正规的(底13,高5的三角形)凹进去了0.5的面积,

    同理

    图二:  红色:8 * 3 / 2 = 12

                  青色:5 * 2 / 2 = 5

                  黄色:7

                  绿色:8 

                  一共:12 + 5 + 7 + 8  + 1= 32 + 1 = 33(加一是应为有个空的格子)

     可是!13(三角形看成一个整体13为它的底) * 5(整体的高) / 2 =32.5  .. 33- 32.5 = 0.5,

     也就是说图二的三角形比正常的要凸出0.5的面积,

   一个凹0.5,一个凸0.5就形成了这个多出来的空的空格了。

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 6th, 2012

趣题:可以一笔画么?

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.2.4

问题1:如何以一笔画的方式用四条直线连接九点,各点只许通过一次?

1

问题2:证明下图中,不可能一笔画穿过所有的点,每个点不能被通过1次以上,不能画斜线。

2

题解:

问题1:

O~)]E)JV_~Z11BG`@W@8$AF

问题2:

我们将一个点与其上下左右相邻的4个点连上边,则得到一个无向图。

问题转换为证明这个无向图不存在Hamilton路径[1]。我们可以用如下方法[2]证明:

我们把所有的点染成黑白两色,相邻的点染上不同的颜色,那么我们的线段两端一定连接的是不同颜色的点。如果存在Hamilton路径,那么一定存在一个序列,黑白交替的出现。
再来看这图,我们发现,染色完成后,一种颜色的点会比另外一种多2个。这种情况下,至少有两个相同颜色的连在一起。所以不可能存在Hamilton路径。证毕

参考文献:

[1]Wikipedia:Hamiltonian path.

[2]方世昌:离散数学(第三版).西安电子科技大学出版社.

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 6th, 2012

组合数的计算

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.2.2

1、给出一个n,对任意的k<n,如何计算所有的C(n,k)?

2、当n,k很大时,怎么判断C(n,k)的奇偶性?

题解:

组合数如果直接根据定义计算:n(n-1)(n-2)…(n-k+1)/k!

那么在计算过程中可能会溢出,而导致最后结果错误。

我们可以利用组合数的性质[1]

C(n,k)=C(n-1,k)+C(n-1,k-1)

这个方程只含加法,所以不会溢出。需要注意的是由于含有重叠子问题, 直接递归计算的效率是极低的,所以我们不出意外的使用动态规划来计算。

还可以进一步优化,就是我们知道C(n,k)=C(n,n-k)[1]。所以如果n-k<k,我们就把k变为n-k来计算。

代码:

#include <cstdio>
using namespace std;
const unsigned N=1+100,K=1+100;
unsigned c[N][K];
int main()
{
    unsigned n,k;
    scanf("%u%u",&n,&k);
    if (n-k<k) k=n-k;
    c[0][1]=0;
    for (unsigned i=0;i<=n;++i) c[i][0]=1;
    for (unsigned i=1;i<=n;++i)
        for (unsigned j=1;j<=i;++j)
            c[i][j]=c[i-1][j]+c[i-1][j-1];
    printf("%u\n",c[n][k]);
    return 0;
}

奇偶性的问题,由于n,k很大,所以不能直接计算组合数的值,因为会越界溢出。所以同样是利用上面的两个技术,用0表示偶数,1表示奇数,f[i][j]表示c[i][j]的奇偶性,则有f[i][j]=(f[i-1][j]+f[i-1][j-1]) mod 2。

代码:

#include <cstdio>
using namespace std;
const unsigned N=1+1000,K=1+1000;
unsigned f[N][K];
int main()
{
    unsigned n,k;
    scanf("%u%u",&n,&k);
    if (n-k<k) k=n-k;
    f[0][1]=0;
    for (unsigned i=0;i<=n;++i) f[i][0]=1;
    for (unsigned i=1;i<=n;++i)
        for (unsigned j=1;j<=i;++j)
            f[i][j]=(f[i-1][j]+f[i-1][j-1])%2;
    printf("%u\n",f[n][k]);
    return 0;
}

我们知道组合数与杨辉三角有很密切的联系[2],实际上杨辉三角第n+1行的第k+1个数,就是C(n,k)。

如果我们将上面的奇偶性按杨辉三角打印出来,将会得到什么呢?

1

1 1

1 0 1

1 1 1 1

1 0 0 0 1

1 1 0 0 1 1

1 0 1 0 1 0 1

1 1 1 1 1 1 1 1

1 0 0 0 0 0 0 0 1

1 1 0 0 0 0 0 0 1 1

1 0 1 0 0 0 0 0 1 0 1

1 1 1 1 0 0 0 0 1 1 1 1

1 0 0 0 1 0 0 0 1 0 0 0 1

1 1 0 0 1 1 0 0 1 1 0 0 1 1

1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

这样似乎看不出什么特别,但是如果我们将1换成“#”,0换成“.”:

#

##

#.#

####

#...#

##..##

#.#.#.#

########

#.......#

##......##

#.#.....#.#

####....####

#...#...#...#

##..##..##..##

#.#.#.#.#.#.#.#

################

没看错,这是一个分形图[3]

参考文献:

[1]Wikipedia:Combination.

[2]Wikipedia:Pascal’s triangle.

[3]Wikipedia:Fractal.

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 5th, 2012

约瑟夫环问题扩展:唐伯虎点秋香

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.2.1

秋香和她的29个丫头排成一个大圆圈;给这个圆圈里的所有人按顺时针的次序编上号,秋香在第28号。现在唐伯虎要说出一个数字,我们就设为X吧,然后圆圈里的人就从1开始顺时针报数,数到X的那一个人就退出圆圈,然后就用这个人的位置号代替X,继续接着从这个人的后面一个人开始报数,数到谁谁就退出;以次类推,直到最后圆圈里只剩下一个人。
聪明唐伯虎应该说一个多大的数字才能保证最后剩下一个人是秋香呢?
号外号外,在异空间中也有个秋香,更有一个苦命的唐伯虎,因为他的秋香有10^7个丫环,不过他幸福的一点是,秋香非常配合他。他会提前给秋香说一个数字,秋香会根据这个数字,选择她的位置,最终俩人幸福美满。假设小唐同学说的数字是X,那么秋香应该站在第几号位置?

题解:

这是约瑟夫环问题[2]的扩展。

为方便处理,我们先把这些姑娘们的编号从0开始计数,n个姑娘按顺时针编号分别为0,1,2,3,…,n-1。

然后我们数x个人吧,一定会数到(x-1) mod n号姑娘的头上。

然后这个姑娘就被拉出去斩了。

现在剩下的n-1个姑娘又排成了1个坏,我们对她们重新编号,以刚才被拉出去斩了的姑娘的下一位姑娘为0号。其实就是做如下置换(m等于刚才被拉出去斩了的姑娘的编号(x-1) mod n):

(m +1) mod n  -> 0

(m+2) mod n  -> 1

(m+3) mod n  -> 2

(m+k) mod n  -> k-1

(m+(n-1)) mod n  -> n-2

我们看到现在问题变为从n-1个姑娘中选秋香了,而且x变成了m+1,也就是原来那个姑娘的编号加1,加1是因为我们是从0计数的。

如果我们用f[i][j]表示在i个姑娘中以数j个人开始,最终剩下的姑娘的编号,那么要求得f[i][j],我们只需要求得f[i-1][(j-1) mod i +1]就行,问题是f[i-1][(j-1) mod i +1]所表示的姑娘是重新编号过的,所以我们只需要把编号给还原回去。

看看我们上面的置换方程:(m+k) mod n  -> k-1,

设旧编号是x’,新编号是x,利用同余理论[1]很容易反推出如何从新编号变回旧编号:x’=(x+m+1) mod n。

也就是说有f[i][j]=(f[i-1][(j-1) mod i + 1]+((j-1) mod i)+1) mod i。

初始条件f[1][]=0。

动态规划解之。

由于姑娘们实际是从1开始编号的,所以我们最后的结果是f[n][(x-1) mod n+1]+1,为什么不是f[n][x]+1呢?因为x可能大于n,实际上这又绕了个圈数回来了,等同于数一个更小的数,所以我们也只需计算不大于n的x对应的f[][x]。

代码:

#include <cstdio>
using namespace std;
const unsigned N=1+100;
int main()
{
    int n,x,f[N][N];
    scanf("%d%d",&n,&x);
    for (int i=1;i<=n;++i) f[1][i]=0;
    for (int i=2;i<=n;++i)
        for (int j=1;j<=i;++j)
            f[i][j]=(f[i-1][(j-1) % i + 1]+((j-1) % i)+1) % i;
    printf("%d\n",f[n][(x-1)%n+1]+1);
    return 0;
}

参考文献:

[1]同余,负数余数,与C/C++中的取模运算.

[2]Wikipedia:Josephus problem.

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 5th, 2012

同余,负数余数,与C/C++中的取模运算

1 Comment, 数学与计算机科学, by Aikilis.

给定一个正整数n,如果两个整数a,b的差a-b是n的倍数,则称a,b模n同余。

记为:

a ≡ b (mod n)

直观来说,就是把0,1,…,n-1排成一个环,我们从0开始顺时针数a个数,与从0开始顺时针数b个数,将数到同一个数。(如果a为负数,则从0开始逆时针数-a个数,b同理)

如果a ≡ b (mod n)且c ≡ d (mod n),则容易证明如下性质:

a+c ≡ b+d (mod n)

a-c ≡ b-d (mod n)

ac ≡ bd (mod n)

这与相等关系是类似的,我们注意到高斯消元法解线性方程组就是基于相等关系的这3个性质,所以高斯消元法也是可以解线性同余方程组的。

很多时候我们说a,b模n同余,也理解为n除a和b将有相同的余数,这是很好理解的,既然a,b在环上的位置是相同的,那么a所在的位置的标号(0,1,…,n-1中的一个)当然与b的相同,而这标号正好就是n除a,b的余数。

如果x是n除a的余数,那么显然有a ≡ x (mod n),然而这种情况下我们可以使用一种更强的记号:

x = a mod n (注意这里是“=”而不是“≡”)

这表明x不仅和a同余,而且是和a同余的数中的最小非负整数。

实际上我们上面所说的余数都是指“正的余数”。这是什么意思呢,让我们再澄清一下余数的定义。

自然数的余数的定义如下:

a,d是自然数且d非零,我们可以证明存在唯一的整数q和r,使得a=qd+r,其中0<=r<d。q被称为商,而r被称为余数。

从这个余数的定义我们可以看到,就是说r = a mod d。

我们再来看看整数的余数的定义[2]

a,d是整数且d非零,则余数r是指满足a=qd+r的整数,其中q是整数且|r|<|d|。

我们注意到这个定义将导致余数的不唯一性。

举个例子,5除8,由于8=1X5+3,所以余数可以是3,又因为8=2X5+(-2),所以余数也可以-2。

在数论中我们通常都取正的那一个作为余数。也就是说n除a的余数在数论中就被认为是与a模n同余的最小非负整数a mod n。

如果n是负数,我们依然可以用符号a mod n表示余数,当然由于n<0,同余的概念已经不能使用了,我们就按照余数的定义取非负的那个。

余数可以方便的计算[1]

a mod n = a-n*floor(a/n)

floor()表示下取整函数[4]

这个公式是很好理解的,用a尽量的除n,或者说把a尽可能的分成n份,每份都是一个整数,那么剩余的不能分的就是其余数。

在高级语言中通常提供取模运算,如C/C++中的%算符,Pascal中的mod算符等。

然而这些算符的含义并不完全等同于数论中的mod运算[3],如果不能认识到这一点,可能会导致程序出现意想不到的错误。

余数的定义多种多样(如上就有两种),而计算机表示数的方法更是多种多样[3][5]。所以取模运算的确切结果取决于具体的编程语言甚至是硬件。

但通常来说,n除a的商q与余数r=a mod n都满足如下关系:

q是整数。
a=nq+r。
|r|<|n|。

这就如前文所言,r可能为正或负,这符号的取值依赖于具体的编程语言,例如Pascal和Algol68就规定结果恒为非负的,而C89甚至根本就没有定义这一行为,全依赖于具体编译器的实现,而C99则规定结果与被除数a同号,98年的C++标准也未定义这行为,直到2011年的C++标准中才规定结果与被除数同号[3]

为了实际编程需要,我们需要了解最常见的编译器,GCC与G++到底是如何定义这些行为的。

我们先从C++编译器(G++)开始,有如下实验程序:

#include <cstdio>
using namespace std;
int main()
{
    int a[]={8,8,-8,-8},b[]={5,-5,5,-5,0};
    for (int i=0;b[i];++i) printf("%2d mod %2d = %2d\n",a[i],b[i],a[i]%b[i]);
    return 0;
}

其运行结果如下:

8 mod     5 =     3

8 mod    -5 =     3

-8 mod     5 =    -3

-8 mod    -5 =    -3

可以发现G++的结果是与被除数同号,这与C++2011是一致的。

在来看看C语言(GCC)的情况,有如下实验程序:

#include <stdio.h>
int main()
{
    int i,a[]={8,8,-8,-8},b[]={5,-5,5,-5,0};
    for (i=0;b[i];++i) printf("%2d mod %2d = %2d\n",a[i],b[i],a[i]%b[i]);
    return 0;
}

其运行结果如下:

8 mod     5 =     3

8 mod    -5 =     3

-8 mod     5 =    -3

-8 mod    -5 =    -3

可以发现GCC的结果也是与被除数同号,这与C99一致。

可见无论是GCC还是G++,它们的取模运算都与我们数论上的取余数有所区别,所以如果我们想在程序中使用数论上的模运算,应该格外小心。

计算机科学中使用数论模运算通常是为了处理与环状结构有关的问题,例如约瑟夫环问题[6]。这些问题中的除数n通常是正数,所以为了应付这类问题,最保险的做法是编写自己的数论模运算函数:

int mod(int a,int n)
{
    int r=a%n;
    if (r<0) return r+n;
    return r;
}

此函数的正确性是基于如下定理[2]

a,n是正数且n>0,r[1],r[2]是n除a的两个余数,其中r[1]为正,r[2]为负,则有r[1]=r[2]+n。

这个定理是显然而易于理解的。

参考文献:

[1]Wikipedia:Modular arithmetic.

[2]Wikipedia:Remainder.

[3]Wikipedia:Modulo operation.

[4]Wikipedia:Floor function.

[5]补码为什么是这样定义的.

[6]Wikipedia:Josephus problem.

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 4th, 2012

最长不下降子序列(LIS)的O(nlogn)算法

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.1.31

在军训的第一天,小班同学还没有安排好队次,大家混着站成了一排,因而有的较矮的同学站在了较高同学中间。现在班长希望指定部分同学向前一步走,出来的这些同学正好是按照由矮到高,不递减的次序排列的,那么,他最多能够指定多少同学向前走呢? 以下面的例子为例:
假定同学身高为(单位很特殊,所以不要纠结单位的问题):
5 7 8 2 3 9 5 8 7 8
那么最多指定同学的策略是:
5 7 8 X X X X 8 X 8 或者: X X X 2 3 X 5 8 X 8
想想怎么找出这个序列。

题解:

经典的最长不下降子序列(LIS)问题。

O(n2)算法:

用f[i]表示恰好以第i个数结尾的不下降子序列的最大长度,a[i]表示第i个数。

则有:

f[i]=1+max{f[j] | j<i,a[j]<=a[i]},如果max{…}不存在,则f[i]=1。

初始条件f[1]=1。

可用动态规划轻松求解f[],f[]中的最大值就是LIS长度。时间复杂度为O(n2)

O(nlogn)算法:

定义一个数组c[],c[p]表示在当前检测的情况下,最长长度为p时,序列结尾的最小值。假设c中元素有m个,表示LIS长度为m。其中c[1]为最长长度为1时,结尾元素的最小值,c[m]为最长长度为m时,结尾元素的最小值,那么,在扫描a中第k个元素时,有如下两类操作:如果a[k] > =c[m],表示当前元素可以放在前面已有的长度为m的序列后,这样就形成了长度为m+1的递增序列。我们将a[k]插入到c[m]后,此时c中元素有m+1个。如果a[k] < c[m],那么找出c中的元素c[l],使得c[l] < =a[k] 并且 c[l+1] > a[k]。这表示a[k]能接在序列长度为l的元素后形成长度为l+1的序列,并且该序列的最后一个元素比原c[l+1]小,于是令c[l+1]=a[k],通过这种方式,我们维护了c数组。容易证明c[]是一直保持有序的,所以在找寻l的时候可以使用二分查找,这使得整个算法的时间复杂度降为O(nlogn)。

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

二月 1st, 2012

趣题:建邮局的最优位置

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.1.30

在一条平直的公路边上有n个小镇,坐标分别为:a[0], a[1], …, a[n],我们需要在这条公路边上修1个邮局,使它到所有小镇距离之和最小,我们应该把邮局修到哪一个位置?

答案:

建在a[0],a[1],…,a[n]的中位数位置上。

题解:

假设只考虑其中的两个小镇a[i]和a[j],邮局建在他们的中间显然比建在他们组成的区间之外更好。

所以如果可以把邮局建在某两个小镇之间,就不要把它建在这两小镇之外。

我们把邮局建在小镇的中位数上,因为这可以使得邮局在尽量多的两个小镇之间。

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

一月 29th, 2012

Floyd-Warshall算法原理简述

No Comments, 数学与计算机科学, by Aikilis.

Floyd-Warshall实际上就是动态规划。

设f[k][i][j]表示第i个结点与第j个结点的中途只经过前k个结点的最短路径的长度。

那么f[k][i][j]=max{f[k-1][i][j],f[k-1][i][k]+f[k-1][k][j]}。

这个方程是如此显然,由于每次计算f[k][][]时只需要用到f[k-1][][],所以对于第一维我们可以只记录当前值,于是Floyd-Warshall算法便如此显然的得到了。

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.

一月 28th, 2012

最大子区间与最大子矩阵

No Comments, 数学与计算机科学, by Aikilis.

ACM校队每日一题 2012.1.28

给定一个数列,求出该数组中最大的区间和。区间和定义为在数列中连续的几个数字之和。
如,在数列1, 6, -4, 8, 3, -5, 2中,最大连续子区间为[1, 6, -4, 8, 3],总和为14。

扩展:给定一个矩阵,求出该矩阵的所有子矩阵中,包含的数字和的最大值。
如,在下面的矩阵中,
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
左下角的子矩阵
9 2
-4 1
-1 8
有最大的和15.

题解:

最大子区间:

设数组为a,长度为n,下标从0开始计数。

令f[i]表示恰好以a[i]结尾的子区间的最大和。

则f[i]=max{a[i],f[i-1]+a[i]},

初始条件为f[0]=a[0],

最后max{f[0],f[1],…f[n-1]}即为最大子区间和。

时间复杂度O(n)。

代码:

#include <cstdio>
using namespace std;
int main(int argc,char* argv[])
{
    int a,f,n,maxsum;
    scanf("%d",&n);
    if (n>0) scanf("%d",&a);
    maxsum=f=a;
    for (int i=1;i<n;++i)
    {
        scanf("%d",&a);
        if ((f=f>0?a+f:a)>maxsum)
            maxsum=f;
    }
    printf("%d\n",maxsum);
    return 0;
}

最大子矩阵:

用a[n][m]表示矩阵,下标从0开始计数。

用f[i][j]表示以第i+1行开始,以第j+1行结束的最大子矩阵和。

则问题转化为:穷举i,j,找出最大的f[i][j]

把第i+1行到第j+1行每一列的数相加,看作是一个数,则求f[i][j]即变成了求最大子区间。时间复杂度O(n2)

代码:

#include <cstdio>
using namespace std;
const unsigned N=1e3;
int a[N][N],f[N][N];
int main(int argc,char* argv[])
{
    int n,m;
    scanf("%d%d",&n,&m);
    for (int i=0;i<n;++i)
        for (int j=0;j<m;++j)
            scanf("%d",&a[i][j]);
    for (int i=0;i<n;++i)
        for (int j=i,t[N]={0};j<n;++j)
        {
            for (int i=0;i<m;++i) t[i]+=a[j][i];
            int g,maxsum;
            maxsum=g=t[0];
            for (int i=1;i<m;++i)
                if ((g=g>0?t[i]+g:t[i])>maxsum)
                    maxsum=g;
            f[i][j]=maxsum;
        }
    int maxsum=f[0][0];
    for (int i=0;i<n;++i)
        for (int j=i;j<n;++j)
            if (f[i][j]>maxsum)
                maxsum=f[i][j];
    printf("%d\n",maxsum);
    return 0;
}

© 2012, Aikilis. 版权所有. 转载请注明出自http://aikilis.tk/.


本WordPress博客由爱写字提供技术支持