叶
叶不归
Unregistered / Unconfirmed
GUEST, unregistred user!
Lee兄:您那个程序我看不懂,修改了一下自个的,再看看现在这个如何:
var
Path: string;
function GetMinPP(m, n, v: Integer): Integer;
var
Tmp: Integer;
procedure AddPath(P: Integer);
begin
Path := Path + IntToStr(P) + ',';
end;
begin
if n > m then
// 翻有最小解的那一堆
begin
n := n + m;
m := n - m;
n := n - m;
end;
Result := -1;
if (m + n <= v) or (m<=0) or (n<=0) or (v<=0) then
//无解情况返回-1
Exit;
if (n mod 2 = 1) and (v mod 2 = 0) then
if m mod 2 = 0 then
begin
n := n + m;
m := n - m;
n := n - m;
end
else
Exit;
if n mod v = 0 then
//正好整除就很简单了
begin
Result := n div v - 1;
end
else
begin
{ 非整除情况 }
Tmp := n mod v;
//Tmp 是小于v的余数: n mod v
if ((v-Tmp) mod 2 = 0) and (n > v) then
//对于n>v时,tmp有可能直接变成0,这种情况比较特殊
begin
AddPath((Tmp + v) div 2);
Result := 1;
end
else
begin
if m < v - Tmp div 2 then
begin
while m*n <> 0do
begin
if m >= n then
begin
AddPath(v-m);
n := n + m*2 -v;
m := v - m;
end
else
begin
AddPath;
m := m + n*2 - v;
n := v - n;
end;
Inc(Result);
end;
Inc(Result);
Exit;
end;
//else
// Exit;
// 本来m要翻至少v-tmp div 2 个子的,但如果m不够数,表示没有翻动的余地了,无解。
Result := 2;
if Tmp = 1 then
//tmp等于1是个很奇怪的情况,如果移n,至少需要三步
begin
if (m mod v = 0) and (m div v < 3) then
//如果移m少于三步,那移m好了
begin
Path := '';
AddPath(v);
if m div v = 2 then
AddPath(v);
Result := m div v;
Exit;
end;
AddPath(1);
//把n变成不是1,再按照一般的解法解。
Tmp := v - 1;
Inc(Result);
end;
{ 这一段是核心原理 }
if Tmp mod 2 = 0 then
// Tmp mod 2=0 表示可以只一次组合成v倍数
begin
AddPath(Tmp div 2);
AddPath(v);
//对于n<v的情况,tmp无法直接变成0,只好往上发展了,因此路径加v
end
else
if Tmp = 1 then
// 1的情况也比较特殊,可以直接减1
AddPath(v div 2 + 1)
else
begin
AddPath(v div 2);
//非1情况先把n变为偶数
AddPath(Tmp div 2 + 1);
//变成偶数就可由v-2i一次性组合成功。
end;
end;
end;
while n >= vdo
//加入大于v的部分,完成!
begin
AddPath(v);
Dec(n, v);
Inc(Result);
end;
if m mod v = 0 then
if m div v < Result then
begin
Result := m div v;
Path := '';
while m <> 0do
begin
AddPath(v);
Dec(m, v);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
m, n, v: Integer;
begin
m := StrToInt(Edit1.Text);
//m = 正面为上
n := StrToInt(Edit2.Text);
//n = 反面为上
v := StrToInt(Edit3.Text);
//v = 翻动个数
Path := '';
Button1.Caption := IntToStr(GetMinPP(m, n, v));
Edit4.Text := Path;
end;
var
Path: string;
function GetMinPP(m, n, v: Integer): Integer;
var
Tmp: Integer;
procedure AddPath(P: Integer);
begin
Path := Path + IntToStr(P) + ',';
end;
begin
if n > m then
// 翻有最小解的那一堆
begin
n := n + m;
m := n - m;
n := n - m;
end;
Result := -1;
if (m + n <= v) or (m<=0) or (n<=0) or (v<=0) then
//无解情况返回-1
Exit;
if (n mod 2 = 1) and (v mod 2 = 0) then
if m mod 2 = 0 then
begin
n := n + m;
m := n - m;
n := n - m;
end
else
Exit;
if n mod v = 0 then
//正好整除就很简单了
begin
Result := n div v - 1;
end
else
begin
{ 非整除情况 }
Tmp := n mod v;
//Tmp 是小于v的余数: n mod v
if ((v-Tmp) mod 2 = 0) and (n > v) then
//对于n>v时,tmp有可能直接变成0,这种情况比较特殊
begin
AddPath((Tmp + v) div 2);
Result := 1;
end
else
begin
if m < v - Tmp div 2 then
begin
while m*n <> 0do
begin
if m >= n then
begin
AddPath(v-m);
n := n + m*2 -v;
m := v - m;
end
else
begin
AddPath;
m := m + n*2 - v;
n := v - n;
end;
Inc(Result);
end;
Inc(Result);
Exit;
end;
//else
// Exit;
// 本来m要翻至少v-tmp div 2 个子的,但如果m不够数,表示没有翻动的余地了,无解。
Result := 2;
if Tmp = 1 then
//tmp等于1是个很奇怪的情况,如果移n,至少需要三步
begin
if (m mod v = 0) and (m div v < 3) then
//如果移m少于三步,那移m好了
begin
Path := '';
AddPath(v);
if m div v = 2 then
AddPath(v);
Result := m div v;
Exit;
end;
AddPath(1);
//把n变成不是1,再按照一般的解法解。
Tmp := v - 1;
Inc(Result);
end;
{ 这一段是核心原理 }
if Tmp mod 2 = 0 then
// Tmp mod 2=0 表示可以只一次组合成v倍数
begin
AddPath(Tmp div 2);
AddPath(v);
//对于n<v的情况,tmp无法直接变成0,只好往上发展了,因此路径加v
end
else
if Tmp = 1 then
// 1的情况也比较特殊,可以直接减1
AddPath(v div 2 + 1)
else
begin
AddPath(v div 2);
//非1情况先把n变为偶数
AddPath(Tmp div 2 + 1);
//变成偶数就可由v-2i一次性组合成功。
end;
end;
end;
while n >= vdo
//加入大于v的部分,完成!
begin
AddPath(v);
Dec(n, v);
Inc(Result);
end;
if m mod v = 0 then
if m div v < Result then
begin
Result := m div v;
Path := '';
while m <> 0do
begin
AddPath(v);
Dec(m, v);
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
m, n, v: Integer;
begin
m := StrToInt(Edit1.Text);
//m = 正面为上
n := StrToInt(Edit2.Text);
//n = 反面为上
v := StrToInt(Edit3.Text);
//v = 翻动个数
Path := '';
Button1.Caption := IntToStr(GetMinPP(m, n, v));
Edit4.Text := Path;
end;