回 帖 发 新 帖 刷新版面

主题:【急求】这两道题怎么做呀?要算法

最近在两道题上卡住了,请大家帮我。(时间限制:1分钟)

一、分正方形问题:
给出一个长为M厘米、宽为N厘米的长方形(M,N均不大于50),要求把它分成最少个数的正方形,并且每一个正方形的边长都为整厘米数。
【输入】两个数,表示M、N的值。
【输出】一个数,表示最少分成的正方形的个数。
【样例】
输入:M=6,N=5。
输出:5(最少分成3×3的正方形2个,2×2的3个,共5个)
【测试数据范围】
共有8组测试数据。
有3组测试数据,N、M均小于7。
有6组测试数据,N、M均小于30。

二、方格取数。
有一个N×N的方阵(1<=N<=20),其中的某些格子里有数字。一个人从左上角走到右下角(只许向下或向右走),问沿途能取到的数字和最大是多少(凡是经过的格子里的数字全部被取到)。
【输入】
第一行是一个数,表示N的值。
第二行是一个数K,表示共有K个方格里有数字。
接下来K行,每行有三个数,分别表示这个数字的行号、列号和数字值。
【输出】
一个数,表示沿途能取到的数字的最大和。
【样例】
输入:
4
4
1,4,5
2,2,3
2,3,4
4,1,6
输出:
7
【测试数据范围】
共有10组测试数据。
有4组测试数据,N小于5,K小于6。
有7组测试数据,N小于10,K小于50。
所有的测试数据,K小于300。

请给出[b]算法[/b]。

回复列表 (共5个回复)

沙发

第一道题暂时没有什么好思路,但是第二道题上倒是有点想法。
(时间限制 1 分钟这也荒谬了点吧……)

第一可以用传说中的深度优先搜索,因为题目中说那个家伙只能往右走或者往下走,那么对于任意时刻,这个人一定会有两种选择,即向右和向下(右下角除外,不过反正一定要踏上)。于是你就可以对每个点进行 dfs 然后用一个变量记录累加和并寻找最大值。
(最大运算量为 2 ^ 39 吧,还是很慢的)

第二可以用快一点的方法。事先建立一个二维数组(记录输入数据的那个不算),然后开始按照逐行扫描的方式进行。比如说,第一行第一个只能就是本格的数值,然后第一行第二个只能是他左边的加上自己,第三个只能是左边的加上自己……然后第二行第一个只能是上边的加自己,而第二行第二个以及其余任何非第一行/第一列的格子都可能且只可能是上面那个加自己或者左边那个加自己,这里判断一下后,便可以对那家伙走到任意一格的最大值都记录下来,到最后输出右下角格子的就可以了。
按行扫描,这个比较快,最大运算量也才几百。







板凳

见下

3 楼

昨天的算法欠妥,其实根本不需要两叉树,只用递归即可。
现将两种算法都列出,其中
function Insert0(n:word):pnode;
procedure mid(p:pnode;i:word);     是两叉树加递归算法
procedure Insert1(step,n:word);    是递归算法
两种方法都算出同样的结果,在borland pascal下编译通过,请Moto参考。
program Routes;
const
     rows=7;MaxRand=1000;
type
    pnode=^node;
    node=record
    location,value:word;
    right,down:pnode;
    end;
var
   a:array[1..rows*rows]of word;
   wmax,wmin,w1:array[1..rows*2-1]of word;
   maximum,minimum,tmp:longint;
function GetNode(l,v:word):pnode;
var
   p:pnode;
begin
     GetMem(p,SizeOf(node));
     p^.location:=l;
     p^.value:=v;
     p^.right:=nil;
     p^.down:=nil;
     GetNode:=p;
end;
procedure Clear;
var
   i:word;
begin
     for i:=1 to 2*rows-1 do
         begin
              w1[i]:=0;
              wmax[i]:=0;
              wmin[i]:=0;
         end;
         maximum:=0;minimum:=100000000;tmp:=0;
end;
procedure init(M:word);
var
   i,j:word;
begin
     Randomize;
     for i:=0 to rows-1 do
         for j:=1 to rows do
             a[i*rows+j]:=Random(M)+1;
     Clear;
end;
function Insert0(n:word):pnode;
var
   p:pnode;
begin
     p:=GetNode(n,a[n]);
     if n=rows*rows then insert0:=GetNode(rows*rows,a[rows*rows]);
     if n mod rows<>0 then p^.right:=Insert0(n+1);
     if n<=rows*(rows-1) then p^.down:=Insert0(n+rows);
     Insert0:=p;
end;
procedure SaveMax;
var
   i:word;
begin
     for i:=1 to 2*rows-1 do wmax[i]:=w1[i];
     maximum:=tmp;
end;
procedure SaveMin;
var
   i:word;
begin
     for i:=1 to 2*rows-1 do wmin[i]:=w1[i];
     minimum:=tmp;
end;
procedure mid(p:pnode;i:word);
begin
     w1[i]:=p^.location;tmp:=tmp+p^.value;
     if p^.right<>nil then mid(p^.right,i+1);
     if (tmp>maximum)and(p^.location=rows*rows)then SaveMax;
     if (tmp<minimum)and(p^.location=rows*rows)then SaveMin;
     if p^.down<>nil then mid(p^.down,i+1);
     tmp:=tmp-p^.value;
end;
procedure PrintTable;
var
   i,j:word;
begin
     for i:=0 to rows-1 do
         begin
         for j:=1 to rows do
             write(a[i*rows+j]:5);
         writeln;
         end;
end;
procedure PrintResult;
var
   i:word;
begin
     for i:=1 to rows*2-1 do
         write(wmax[i]:5);
     writeln('   Max:=',Maximum);
     for i:=1 to rows*2-1 do
         write(wmin[i]:5);
     writeln('   Min:=',Minimum);
end;
procedure Insert1(step,n:word);
var
   k:word;
begin
     w1[step]:=n;
     if n=rows*rows then
        begin
             tmp:=0;
             for k:=1 to 2*rows-1 do inc(tmp,a[w1[k]]);
             if tmp>Maximum then SaveMax;
             If tmp<Minimum then SaveMin;
        end else
        begin
             if n mod rows<>0 then Insert1(step+1,n+1);
             if n<=rows*(rows-1) then Insert1(step+1,n+rows);
        end;
end;


var
   p:pnode;
   i:word;
begin
     writeln('  Table from ',1,' to ',rows*rows);
     Init(MaxRand);
     PrintTable;

     p:=insert0(1);
     mid(p,1);
     PrintResult;
     Clear;

     insert1(1,1);
     PrintResult;
end.

4 楼

procedure init(M:word);{初始函数修改}
var
   i,j:word;
begin
     Randomize;
     for i:=0 to rows-1 do
         for j:=1 to rows do
             if boolean(random(2))then 
                a[i*rows+j]:=Random(M)+1
                else a[i*rows+j]:=0;
     Clear;
end;

5 楼

xjwxwy

我来回复

您尚未登录,请登录后再回复。点此登录或注册