整数划分(文件名:separate.c/cpp/pas)

整数划分(文件名:separate.c/cpp/pas)


 
如何把一个正整数N(N长度<20)划分为M(M>1)个部分,使这M个部分的乘积最大。N、M从键盘输入,输出最大值及一种划分方式。
输入数据:
    第一行一个正整数T(T<=10000),表示有T 组数据。
    接下来T行每行两个正整数N,M。
 
输出数据:
对于每组数据
第一行输出最大值。
第二行输出划分方案,将N 按顺序分成M个数输出,两个数之间用空格格开。
 
样例
  输入文件:separate.in
1
199 2
输出文件:separate.out
171
19 9

===========================

输出方案的DP

----------------------

f[i,j]表示前i个,分j次的最大价值....

v[i,j]表示这一阶段是由...转换而来的...

-----------------------------------------------------

注意数据范围...

最后在递归输出解...

=========================================

var
  m:longint;
  n:int64;
  t,t1:longint;
  st:ansistring;
  g:array[1..20,1..20]of int64;
  f,v:array[0..20,0..20]of int64;
procedure init;
begin
  assign(input,'separate.in');
  assign(output,'separate.out');
  reset(input); rewrite(output);
end;

procedure terminate;
begin
  close(input); close(output);
  halt;
end;

function min(a,b:longint):longint;
begin
  if a<b then exit(a);
  exit(b);
end;

function max(a,b:int64):int64;
begin
  if a>b then exit(a);
  exit(b);
end;

procedure print(l,m:int64);
var
  i:longint;
begin
  if m=0 then exit;
  print(v[l,m],m-1);
  for i:=v[l,m]+1 to l do write(st[i]);
  write(' ');
end;

procedure main;
var
  i,j,k:longint;
  len:longint;
  sum:int64;
begin
  readln(t1);
  for t:=1 to t1 do
    begin
      readln(n,m);
      str(n,st);
      len:=length(st);
      for i:=1 to len do
        begin
          sum:=0;
          for j:=i to len do
            begin
              sum:=sum*10+ord(st[j])-48;
              g[i,j]:=sum;
            end;
        end;
        
      for i:=0 to len do
        for j:=0 to m do
          f[i,j]:=-1;
      f[0,0]:=1;
          
      for i:=1 to len do
        for k:=1 to min(m,i) do
          for j:=1 to i do
            begin
              //writeln(i,' ',j,' ',k);
              //writeln(f[i,k],' ',f[j-1,k-1],' ',g[j,i]);
              if f[j-1,k-1]*g[j,i]>f[i,k] then
                begin
                  f[i,k]:=f[j-1,k-1]*g[j,i];
                  v[i,k]:=j-1;
                end;
              //writeln(f[i,k],' ',f[j-1,k-1]);
              //writeln;
            end;
      writeln(f[len,m]);
      print(len,m);
    end;
end;

begin
  init;
  main;
  terminate;
end.


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值