procedure TForm1.Button1Click(Sender: TObject);
var
Color:Array[1..10]of Integer;
String1:String;
i,j,k:Integer;
begin
Color[1]:=111;
//以下是对颜色进行赋值;
Color[2]:=222;//假设1表示红,2表示黄,3表示蓝。
Color[3]:=333;//在一个桶内能够出现的一共只有十个组合。
Color[4]:=122;
Color[5]:=122;
Color[6]:=211;
Color[7]:=233;
Color[8]:=311;
Color[9]:=322;
Color[10]:=123;
String1:='一共有以下几种组合:'+#13;
for i:=1 to 10do
for j:=1 to 10do
for k:=1 to 10do
begin
if Color+Color[j]+Color[k]=666 then
String1:=String1+InttoStr(Color)+InttoStr(Color[j])+InttoStr(Color[k])+#13;
end;
ShowMessage(String1);
//显示效果可能不太好,自己在上面改一下。
end;
ASCII基本上等于没答(因为这个方法谁都知道——这是我第一个排除的方案)。
lnboy的方法比较有新意,但是如果不加 if ... then
则肯定会产生不符合约束条件的方案,
但是加了这个约束仍然不能避免不符合约束条件的结果...
to xinjia:
>>用递归算法最简单
别光说不练呀。您只要将算法的核心思想说出来就可以了,实现代码可以由我来写。
(悄悄的说:“在p3的机器上跑了两个多小时才出结果”——这个问题好像不只50分喲)
我——冥思苦想中...
哈哈!昨天晚上摆平了!!!
function BallInBox(N:Integer):Integer;
var
Ball,Box:array of Integer;
proceduredo
Level(Level:Integer);
var //穷举在目前的盒子占用情况下,第Level种颜色的球的可能摆放方式组合 (Level=0..N-1)
a,j,k:Integer;
mstr:String;
procedure PN(M:Integer);
var //计算第Level种颜色的球中,第M个的可能位置
i,s:Integer;
begin
if M=N then
begin
do
Level(Level+1);
exit;
end;
if M=0 then
s:=0
else
s:=Ball[a+M-1];
//起始盒数不能比前面的相同颜色的球小
for i:=s to N-1do
if Box<N then
//若第i个盒子还有空间
begin
Ball[a+M]:=i;
//将第a+M个球放到第i个盒子中
Inc(Box);
PN(M+1);
Dec(Box);
end;
end;
begin
if Level=N then
begin
mstr:='';
for j:=0 to N-1do
begin
for k:=0 to N*N-1do
if Ball[k]=j then
mstr:=mstr+IntToStr(k div N);
//N*N个球中第k个球的颜色
mstr:=mstr+' ';
end;
Form1.Memo1.Lines.Add(mstr);
Inc(Result);
exit;
end;
a:=N*Level;
PN(0);
end;
begin
Result:=0;
SetLength(Ball,N*N);
SetLength(Box,N);
FillChar(Ball[0],N*N*4,0);
FillChar(Box[0],N*4,0);
do
Level(0);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
TWord;
begin
with Memo1do
begin
Clear;
Lines.begin
Update;
T:=GetTickCOunt;
Caption:=Format('共%d个组合,耗时%d毫秒',[BallInBox(SpinEdit1.Value),GetTickCount-T]);
Lines.EndUpdate;
end;
end;
增强版:
function BallInBox(BallColorNum,BallNumPerColor,
BoxNum,BoxSpace,MinBallNumInBox:Integer):Integer;
//顾名思义
var
Ball,Box:array of Integer;
proceduredo
Level(Level:Integer);
var //穷举在目前的盒子占用情况下,第Level种颜色的球的可能摆放方式组合
a,j,k:Integer;
mstr:String;
procedure PN(M:Integer);
var
i,s:Integer;
begin
//计算第Level种颜色的球中,第M个的可能位置
if M=BallNumPerColor then
begin
do
Level(Level+1);
exit;
end;
if M=0 then
s:=0
else
s:=Ball[a+M-1];
//起始盒数不能比前面的相同颜色的球小
for i:=s to BoxNum-1do
if Box<BoxSpace then
//若第i个盒子还有空间
begin
Ball[a+M]:=i;
//将第a+M个球放到第i个盒子中
Inc(Box);
PN(M+1);
Dec(Box);
end;
end;
begin
if Level=BallColorNum then
begin
mstr:='';
for j:=0 to BoxNum-1do
begin
if Box[j]<MinBallNumInBox then
exit;
for k:=0 to BallColorNum*BallNumPerColor-1do
if Ball[k]=j then
mstr:=mstr+IntToStr(k div BallNumPerColor);
//第k个球的颜色
mstr:=mstr+#9;
end;
Form1.Memo1.Lines.Add(mstr);
Inc(Result);
exit;
end;
a:=BallNumPerColor*Level;
PN(0);
end;
begin
Result:=0;
if (BallColorNum*BallNumPerColor>BoxNum*BoxSpace) //球的总数大于总空间数
or (BallColorNum*BallNumPerColor<BoxNum*MinBallNumInBox) then
//不满足每盒最小球数
exit;
SetLength(Ball,BallColorNum*BallNumPerColor);
SetLength(Box,BoxNum);
FillChar(Ball[0],BallColorNum*BallNumPerColor*4,0);
FillChar(Box[0],BoxNum*4,0);
do
Level(0);
end;
{
TBuffer 可控制增量的缓冲区类
用于高速在末尾添加数据,并提供了缓冲区溢出处理事件
By creation_zy
2002-3-15
}
type
TBuffer=class
private
FBufferChar;
FMaxBufSize:Integer;
FIncreasement:Integer;
FContentSize:Integer;
FCapacity: Integer;
function GetAsString: String;
function Enlarge(NewLen:Integer):Boolean;
public
OnBufFullrocedure;
property MaxBufSize:Integer read FMaxBufSize;
property ContentSize:Integer read FContentSize;
property Capacity:Integer read FCapacity;
property Increasement:Integer read FIncreasement;
property AsString:String read GetAsString;
function WriteBuf(PChar;Len:Integer):Boolean;
procedure ClearBuf(FreeMemory:Boolean=true);
constructor Create(MaxSize:Integer=0;IncreaseSize:Integer=32768);
//缺省容量上限为无限大,增量为32K
destructor Destroy;
override;
end;
implementation
{ TBuffer }
procedure TBuffer.ClearBuf(FreeMemory: Boolean);
begin
if FreeMemory then
begin
FreeMem(FBuffer);
FBuffer:=nil;
FCapacity:=0;
end;
FContentSize:=0;
end;
constructor TBuffer.Create(MaxSize: Integer;
IncreaseSize: Integer);
begin
FBuffer:=nil;
if IncreaseSize>0 then
FIncreasement:=IncreaseSize
else
FIncreasement:=32768;
if MaxSize<0 then
FMaxBufSize:=0
else
FMaxBufSize:=MaxSize;
FContentSize:=0;
FCapacity:=0;
OnBufFull:=nil;
end;
destructor TBuffer.Destroy;
begin
FreeMem(FBuffer);
inherited;
end;
function TBuffer.Enlarge(NewLen: Integer): Boolean;
var
PChar;
Len,IncNum:Integer;
begin
Result:=false;
if NewLen<FContentSize then
//新的长度无法容纳已有的内容
exit;
if (FMaxBufSize>0) and (NewLen>FMaxBufSize) then
begin
if Assigned(OnBufFull) then
begin
IncNum:=NewLen-FCapacity;
//保存增量
OnBufFull;
if FContentSize=0 then
//如果用户在 OnBufFull 事件中已经清空了缓冲区
Result:=Enlarge(IncNum);
end;
exit;
end;
Len:=FIncreasement*((NewLen+FIncreasement-1) div FIncreasement);
if (FMaxBufSize>0) and (Len>FMaxBufSize) then
Len:=FMaxBufSize;
try
GetMem(P,Len);
except
if Assigned(OnBufFull) then
begin
IncNum:=Len-FCapacity;
//保存增量
OnBufFull;
if FContentSize=0 then
//...
Result:=Enlarge(IncNum);
end;
exit;
end;
Result:=true;
Move(FBuffer^,P^,FContentSize);
FreeMem(FBuffer);
FCapacity:=Len;
FBuffer:=P;
end;
function TBuffer.GetAsString: String;
begin
SetLength(Result,FContentSize);
Move(FBuffer^,Result[1],FContentSize);
end;
function TBuffer.WriteBuf(P: PChar;
Len: Integer): Boolean;
var
PCChar;
begin
if FContentSize+Len>FCapacity then
Result:=Enlarge(FContentSize+Len)
else
Result:=true;
if Result then
begin
PC:=FBuffer+FContentSize;
Move(P^,PC^,Len);
Inc(FContentSize,Len);
end;
end;
将上面的算法中的Memo1.Lines.Add(mstr);改为:
mstr:=mstr+#13#10;
Buf.WriteBuf(@mstr[1],Length(mstr));
将 function BallInBox 的执行部分改为:
begin
Result:=0;
if (BallColorNum*BallNumPerColor>BoxNum*BoxSpace) //球的总数大于总空间数
or (BallColorNum*BallNumPerColor<BoxNum*MinBallNumInBox) then
//不满足每盒最小球数
exit;
Buf:=TBuffer.Create;
//*************
SetLength(Ball,BallColorNum*BallNumPerColor);
SetLength(Box,BoxNum);
FillChar(Ball[0],BallColorNum*BallNumPerColor*4,0);
FillChar(Box[0],BoxNum*4,0);
do
Level(0);
Form1.Memo1.Text:=Buf.AsString;
//*************
Buf.Free;
//**************
end;