整数划分(文件名: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.