某個欄位的數目相加後再對照某個數目 |
尚未結案
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
|
海星
高階會員 發表:41 回覆:217 積分:106 註冊:2003-01-09 發送簡訊給我 |
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
|
海星
高階會員 發表:41 回覆:217 積分:106 註冊:2003-01-09 發送簡訊給我 |
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
|
pillar62
資深會員 發表:9 回覆:324 積分:271 註冊:2002-04-15 發送簡訊給我 |
你好
應該可以用多個迴圈的方式處理,例如
var i, j : integer;
begin
j := 0;
for i := 1 to 10 do
begin
j := j qr.fields[i].value;
for i := 1 to 10 do
begin
j := j qr.fields[i].value;
if j := 10 then
break;
end;
if j := 10 then
break;
end;
end;
試試看吧 Pillar Wang
------
Pillar Wang |
海星
高階會員 發表:41 回覆:217 積分:106 註冊:2003-01-09 發送簡訊給我 |
引言: 你好 應該可以用多個迴圈的方式處理,例如 var i, j : integer; begin j := 0; for i := 1 to 10 do begin j := j qr.fields[i].value; for i := 1 to 10 do begin j := j qr.fields[i].value; if j := 10 then break; end; if j := 10 then break; end; end; 試試看吧 Pillar Wang你的程式碼有誤,「用程式碼求組合」的做法,是歷屆每個學校資訊系的學校作業,他這題只是作業的變形,以前在學校自己寫過這類作業的人,早就會寫了,根本不用幫他操心,你只需跟他講方法就好了,既然都「交代過」這題只是在求組合,那 coding 的工作還是交還給原作者自己去寫,不用去幫他操心,反正對電腦來講,根本都是一分鐘就幫你解出解答了,沒必要寫什麼較快的方法出來,在想怎樣寫最快的方法的時候,程式碼早就寫好了。 還有這題要小心, 1 1 2 3 3 也是等於 10,他好像沒有講數字不可以重複使用 ,所以 1 1 2 3 3應該也是合乎條件。 |
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
Target number: N var
// N = sum(the number in the record whose seq is in TargetSeqs)
TargetSeqs: TList; // 1. UnitSeqs is a dynamic array
// 2. Assume its index starts from 1(In Delphi, it starts from 0).
// 3. n = sum(the number in the record whose seq is in UnitSeqs[n])
UnitSeqs: array of TList; Table: TTable/TADOTable/TQuery/TList/...; function FindTarget(N: integer): boolean;
var
temp_seqs: TList;
begin
// init
Result := False; TargetSeqs.Clear; AdjustLength(UnitSeqs); // UnitSeqs has at least N-1 TLists for i := 1 to N-1 do
UnitSeqs[i].Clear; // search
Table.Open;
while not Table.Eof do
beign
val := ...; // the number in the current record
seq := ...; // the seq num in the current record
if val = N then
begin
TargetSeqs.Add(Pointer(seq));
Result := True;
Break;
end
else if val < N then
begin
temp_seqs := TList.Create;
temp_seqs.Add(Pointer(seq));
Result := FindCombination(N, val, temp_seqs);
temp_seqs.Free; if Result then
Break;
end; Next;
end;
Table.Close;
end; function FindCombination(N, M: integer; MSeqs: TList);
var
i, j: integer;
temp_seqs: TList;
begin
Result := False;
i := N-M; if UnitSeqs[i].Count <> 0 then
begin
// TargetSeqs = UnitSeqs[i] MSeqs
MergeList(TargetSeqs, UnitSeqs[i], MSeqs);
Result := True;
Exit;
end; if UnitSeqs[M].Count = 0 then
CopyList(UnitSeqs[M], MSeqs); temp_seqs := TList.Create; for j := 1 to i-1 do
if UnitSeqs[j].Count <> 0 then
begin
MergeList(temp_seqs, UnitSeqs[M], UnitSeqs[j]);
Result := FindCombination(N, M j, temp_seqs);
if Result then
Break;
end; temp_seqs.Free;
end; _________________________
Programming is a passion
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
|
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
你好. 这三个函式的功能和它们的名字基本一致, 具体如下: 1. 每次调用FindTarget时, N可能不同. 需要检查UnitSeqs的长度, 保证它至少有N-1个TList. procedure AdjustLength(N: integer);
var
i, old_high: integer;
begin
old_high := High(UnitSeqs);
if old_high < N-2 then
begin
SetLength(old_high, N-1);
for i := old_high 1 to N-2 do
UnitSeqs[i] := TList.Create;
end;
end; 2. NotShareSeq测试两个TList中没有相同的序号. function NotShareSeq(List1, List2: TList): boolean;
var
i: integer;
begin
Result := True;
for i := 0 to List1.Count-1 do
if List2.IndexOf(List1[i]) <> -1 then
begin
Result := False;
Break;
end;
end; 3. MergeList相当于List的Add运算: Des := Src1 Src2. procedure MergeList(Des, Src1, Src2: TList);
var
i: integer;
begin
Des.Clear;
for i := 0 to Src1.Count-1 do
Des.Add(Src1[i]);
for i := 0 to Src2.Count-1 do
Des.Add(Src2[i]);
end; 注意在这里我没有用pseudo-code, 而是100Þlphi. UnitSeqs的Index是从0开始的, 与上面算法的假设不一致, 在实现算法时需要对Index作些转换. _________________________
Programming is a passion
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
yyu10先進你好:
不好意思想在請教你幾個問題
1. CopyList函式是在執行哪些動作呢?
2. AdjustLength(N: integer)中的N值是要取哪個值輸入呢?是不是我要求10的和就輸入10就可以呢?
3. 在AdjustLength函式中有一行SetLength(old_high, N-1) ,old_high是不是要改成UnitSeqs呢?還是其他?
4. UnitSeqs[i].Count是什麼意思呢?
真不好意思,您已經給了我解答,我卻還再次的麻煩您,還望請見諒!!謝啦! 發表人 - adrain 於 2005/03/02 15:21:53
|
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
引言: 1. CopyList函式是在執行哪些動作呢?CopyList相当于List的=运算: Des := Src. procedure CopyList(Des, Src: TList); var i: integer; begin Des.Clear; for i := 0 to Src.Count-1 do Des.Add(Src[i]); end; 引言: 2. AdjustLength(N: integer)中的N值是要取哪個值輸入呢?是不是我要求10的和就輸入10就可以呢?对. 引言: 3. 在AdjustLength函式中有一行SetLength(old_high, N-1) ,old_high是不是要改成UnitSeqs呢?還是其他?对. 应该是 SetLength(UnitSeqs, N-1); 引言: 4. UnitSeqs[i].Count是什麼意思呢?UnitSeqs[i]是TList, UnitSeqs[i].Count是UnitSeqs[i]中元素的数目. 引言:真不好意思,您已經給了我解答,我卻還再次的麻煩您,還望請見諒!!謝啦!不用客气. 你提了一个有趣问题, 尝试解决它是种乐趣. _________________________ Programming is a passion 發表人 - yyu10 於 2005/03/02 18:03:40 |
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
yyu10先進你好:
終於把你給我的程式給試跑了一下,但是跑出來的結果感覺好像跟我的需求有些不太相同,可能是我描述的不夠詳細吧!!,雖然我想獨自自己來修改程式,但無奈你用的技術對我來說深了許多,想下手去修改卻不知如何下手,所以我也就只能再向你求助一下
而我的需求是如上三個圖,假設我要求出總和等於5,只要能將欄位中的Val值加總等於5,然後再記錄每個數目的序號就可以,那至於如加總5,則只要是每個數目是Int且大於零,如同5有7種加法,6有11種加法,7有15種加法,只要是這樣的方式能達到所要的總和即可,謝謝!!
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
引言: 比如, 用到了數目 2, 而數目 2 出現在 8 和 9 上 那麼, 和 8 的組合算一種, 和 9 的組合也算一種 還是 8 或 9 任選一個出來就好?Brian77先進你好: 比如我要總和等於5,那要用何種數目去組合都可以只要能達成迴圈就停止,如上圖5可已由一個5就可以達成,5也可以由一個4跟一個1,也可以5=3 2,也可以5=3 1 1,也可以5=2 1 1 1,更可以5=1 1 1 1 1,反正不管怎麼加只要[其中一種]方式能加起來等於5就好,然後並紀錄那幾筆能加起來等於5的數目的序號,並結束迴圈,只是數目的型態是[整數]且[大於0]即可 那如果要總和=10,而已經先行找到一筆數目2,那若又恰巧找到一筆數目8,那就記錄這兩筆的樹目跟序號就可離開 又比如假設要總和=10,先行找到一筆數目1,然後又恰巧找到一筆數目9,那就記錄這兩筆的樹目跟序號就可離開 又比如假設要總和=10,先行找到一筆數目1,然後又找到一筆數目2,又恰巧找到數目7,這三筆加總等於10,那就記錄這3筆的樹目跟序號就可離開 反正不管如何加總,只要其中一種方式可以先達成加總=10,那就可以達成我想要的需求了 發表人 - adrain 於 2005/03/03 13:53:07 |
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
定義一個 NMList: TStringList;
和一個 function FindAns(mSum,index:integer):String;
NMList:=TStringList.Create; // 開檔 ... // 先從數據讀入 NMList while not Query1.EoF do begin NMList.Add(IntToHex(Query1.FieldByName('數目').asInteger,8) Query1.FieldByName('序號').asString); Query1.Next; end; NMList.Sort; // 排序 mAnswer:=FindAns(10,0); if mAnswer='' then ShowMessage('找不到' ) else ShowMessage(mAnswer);函式內容: function TForm1.FindAns(mSum,index:integer):String; var mStr:String; n:integer; begin Result:=''; while (index |
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
|
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
比如要總和等於10, 以你在最上面给的那幾筆紀錄为例 算法中的While迴圈每运算一遍, UnitSeqs(n)中的值会发生相应的变化, 直到找到一个等于10的组合为止. 运算 1:
紀錄: 序號(1), 數目(1)
UnitSeqs(1): 序號 1(數目 1) While迴圈第一遍运算结束后, UnitSeqs(1), 既Delphi代码中的UnitSeqs[0], 应该有一个元素(序號1). UnitSeqs[0].Count = 1
LongInt(UnitSeqs[0][0]) = 1 运算 2:
紀錄: 序號(2), 數目(2)
UnitSeqs(1): 1(1)
UnitSeqs(2): 2(2)
UnitSeqs(3): 1(1), 2(2) While迴圈第二遍运算结束后,
UnitSeqs(2), 既Delphi代码中的UnitSeqs[1], 应该有一个元素(序號2). UnitSeqs[1].Count = 1
LongInt(UnitSeqs[1][0]) = 2 UnitSeqs(3), 既Delphi代码中的UnitSeqs[2], 应该有两个元素(序號1, 序號2). UnitSeqs[2].Count = 2
LongInt(UnitSeqs[2][0]) = 1 (序號1)
LongInt(UnitSeqs[2][1]) = 2 (序號2) 运算 3:
紀錄: 序號(3), 數目(4)
UnitSeqs(1): 1(1)
UnitSeqs(2): 2(2)
UnitSeqs(3): 1(1), 2(2)
UnitSeqs(4): 3(4)
UnitSeqs(5): 1(1), 3(4)
UnitSeqs(6): 2(2), 3(4)
UnitSeqs(7): 1(1), 2(2), 3(4) 叙述同上相似. 运算 4:
紀錄: 序號(4), 數目(1)
UnitSeqs(1): 1(1)
UnitSeqs(2): 2(2)
UnitSeqs(3): 1(1), 2(2)
UnitSeqs(4): 3(4)
UnitSeqs(5): 1(1), 3(4)
UnitSeqs(6): 2(2), 3(4)
UnitSeqs(7): 1(1), 2(2), 3(4)
UnitSeqs(8): 1(1), 2(2), 3(4), 4(1) 叙述同上相似. 运算 5:
紀錄: 序號(5), 數目(3)
UnitSeqs(1): 1(1)
UnitSeqs(2): 2(2)
UnitSeqs(3): 1(1), 2(2)
UnitSeqs(4): 3(4)
UnitSeqs(5): 1(1), 3(4)
UnitSeqs(6): 2(2), 3(4)
UnitSeqs(7): 1(1), 2(2), 3(4)
UnitSeqs(8): 1(1), 2(2), 3(4), 4(1) UnitSeqs[7]不是空的, 表明有等于7的組合. 由于7 3=10, 所以迴圈终止, 结果应该是 1(1), 2(2), 3(4), 5(3). adrain, 请你用你在最上面给的那幾筆紀錄来测试你的程式, 在While迴圈结束的地方设Break Point, 对照上面的中间结果检查UnitSeqs中的值是否正确. 發表人 - yyu10 於 2005/03/03 20:04:25
|
jimmy_wei
高階會員 發表:9 回覆:176 積分:147 註冊:2003-08-28 發送簡訊給我 |
|
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
adrain, 请你在这里下载源码和测试程式, 用的是Delphi7. http://users.tpg.com.au/adslspj5/ktop/combination_2.zip 發表人 - yyu10 於 2005/03/04 09:32:21
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
感謝Brian77, yyu10兩位先進,您二位的程式碼都是我要的結果,真是謝謝兩位的幫助
可是現在還有一件事情相求,就是因為現在我是要由資料庫擷取資料出來,那資料庫裡面的筆數可能有上萬筆,若一次全部叫出來,並先暫存於TStrinngList或其他,那過程就會變得很遲緩,所以如果改成直接在資料庫上查詢,不知是否可以自由的移動指標到想要的資料上呢?用Query.Next好像行不通,若又用Query.MoveBy(Index)也只能往前或往後移幾個Index,卻不能直接指定第幾筆資料,不知您有其他更好的方式可以解決這個問題嗎?
|
Brian77
中階會員 發表:8 回覆:114 積分:94 註冊:2002-05-17 發送簡訊給我 |
Query1: TADOQuery; // 或其它 var mAnswer:String; begin Query1.Close; Query1.SQL.Clear; Query1.SQL.Add('SELECT 序號,數目 FROM 表格 ORDER BY 數目'); Query1.Open; mAnswer:=FindAns(10); if mAnswer='' then ShowMessage('找不到' ) else ShowMessage(mAnswer); end; function FindAns(mSum:integer):String; var mStr:String; n,mSN:integer; begin Result:=''; while not Query1.EoF do begin n=Query1.FieldByName('數目').asInteger; if n=mSum then begin Result:=Query1.FieldByName('序號').asString; exit; end; if n>mSum then exit; mSN:=Query1.FieldByName('序號').asInteger; // Query1.Next; Result:=FindAns(mSum-n); if Result<>'' then begin Result:=Query1.FieldByName('序號').asString ',' Result; exit; end; // Query1.Locate('序號',[SN]); Query1.Next; end; end;其中 Query1.Locate 那一行.. 太久沒用, 忘了 TADOQuery 有沒有這 method.. 如果資料庫是 Paradox, 則使用 TTable 配合 index 設為數目, 定位用 Bookmark 或 Locate 都可以 如果資料庫是 Access 或 DBMS, 則使用 TADOQuery 之類的, 在定位上嘛, 找找看類似 locate 或 find, 如果都沒有則可在函數中計算 next 了幾筆, 再移回來. 這個我要回公司才有工具查了. |
yyu10
中階會員 發表:9 回覆:99 積分:96 註冊:2005-02-18 發送簡訊給我 |
UnitSeqs 中记录着已经搜索过的数目所有可能的组合, 所以没有必要把指標移回去, 也就是说用 Next 就足够了. FindTarget总能找到第一个符合条件的组合. Query1: TADOQuery 或 TQuery; function FindTarget(N: integer): boolean;
var
i: integer;
temp_seqs: TList;
val, seq: integer;
begin
// 前面没有变动
...... // search
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add('SELECT 序號,數目 FROM 表格');
Query1.Open;
while not Query1.Eof do
begin
val := Query1.FieldByName('數目').AsInteger;
seq := Query1.FieldByName('序號').AsInteger; // 中间没有变动
......
if Result then
Break;
Query1.Next;
end;
end; 算法的其它部分不用变动. 注意在 Query1 中不要加 Order by, 这并不会影响算法的效率. 另外, Order by会使较小的数目先用光, 留下较大的数目没法组成有效的组合. 比如, 11..122..233..344..455..566..677..7..., 从1到5可以构成10, 而单独用6及6以上的数目是没发构成10的. 如果你的程序需要反复在表格中寻找组合的话, 随机地从表格中读数可以得到更多结果. 發表人 - yyu10 於 2005/03/05 11:59:26
|
ko
資深會員 發表:28 回覆:785 積分:444 註冊:2002-08-14 發送簡訊給我 |
|
adrain
一般會員 發表:39 回覆:28 積分:13 註冊:2004-07-27 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |