2017年5月29日 星期一
2017年5月22日 星期一
b547 巧克力口味
/*
b547-巧克力口味
*/
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
const int MaxR = 10;
set <string> rel[MaxR]; // 最多 10 種 關係
map <int , int> c2n;
string rs(8,'?');
string c6(6,' ');
int getn(int i)
{
int j=c2n[ c6[i] ];
j += c2n[ c6[i+1] ];
return j;
}
// 以遞迴 將某一關係的所有編號建立 存入 rel[si]中
string ss[]={"PBY","SCT"};
void setr(int si, int p, int q)
{
int i,j;
if(q==6) // 已 6個字元了
{
bool mk[10];
string one="";
memset(mk,0,sizeof(mk));
for(i=0; i<6; i+=2)
{
j= getn(i);
if( mk[j] ) return; // 出現過,不合
mk[j] = true;
one += char('0'+j);
}
rel[si].insert(one); // 可以的關係編號 加入 rel[si] 中
//// cout << si <<':' << one << endl; /////
}
else // 完成第 q 個字元,遞迴下一字元 q+1
{
if( rs[p+q]=='?' ) // 目前這個位置為 ? 偶則以 PBY各代1次、 奇則以 SCT各代1次
for(i=0; i<3; ++i)
{
c6[q] = ss[q%2][i]; setr(si, p, q+1);
}
else
{
c6[q] = rs[p+q]; setr(si, p, q+1);
}
}
}
string x,y,z; // 將nine切成3部份
int r; //共 r 個關係
bool ok() // 任一個關係 最少要有 某一列 3個巧克力 符合它
{
for(int si=0; si<r; ++si)
{
if( !( rel[si].find(x)!=rel[si].end() || rel[si].find(y)!=rel[si].end() || rel[si].find(z)!=rel[si].end() ) ) return false;
}
return true;
}
int main(void)
{
int i,j,k,t ,n;
char c;
c2n.clear();
c2n['P']=0; c2n['B']=3; c2n['Y']=6;
c2n['S']=1; c2n['C']=2; c2n['T']=3;
cin >> r;
for(i=0; i<r; ++i)
{
cin >> t;
for(j=0; j<t*2; ++j)
{
cin >> rs[j+2];/// >> rs[j+3];
}
/// cout << i <<':' << rs << endl; ////
if(t==3) setr(i,2,0); // 第i個關係,從第2字元、已轉了0個
else // t=2 , 前?? 及後 ?? 各一次
{
setr(i,0,0); // 第i個關係,從第0字元、已轉了0個
rs[6] = rs[7] ='?';
setr(i,2,0); // 第i個關係,從第2字元、已轉了0個
}
}
string nine="123456789";
// cout << nine << endl; 1~9 九位數,全排列 共 9! = 362880
int cnt=0;
do
{
x=nine.substr(0,3); y=nine.substr(3,3); z=nine.substr(6,3);
// cout << x <<',' << y <<',' << z <<'\n';
if( ok() ) ++cnt;
} while( next_permutation(nine.begin(),nine.end() ) );
cout << cnt << endl;
// system("pause");
return 0;
}
/*
3
3 B S Y S P C
3 P T B C Y T
3 P S B T Y C
3
3 B S Y ? ? C
2 B C Y T
3 P S ? ? Y C
==========
6
24
*/
b547-巧克力口味
*/
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
using namespace std;
const int MaxR = 10;
set <string> rel[MaxR]; // 最多 10 種 關係
map <int , int> c2n;
string rs(8,'?');
string c6(6,' ');
int getn(int i)
{
int j=c2n[ c6[i] ];
j += c2n[ c6[i+1] ];
return j;
}
// 以遞迴 將某一關係的所有編號建立 存入 rel[si]中
string ss[]={"PBY","SCT"};
void setr(int si, int p, int q)
{
int i,j;
if(q==6) // 已 6個字元了
{
bool mk[10];
string one="";
memset(mk,0,sizeof(mk));
for(i=0; i<6; i+=2)
{
j= getn(i);
if( mk[j] ) return; // 出現過,不合
mk[j] = true;
one += char('0'+j);
}
rel[si].insert(one); // 可以的關係編號 加入 rel[si] 中
//// cout << si <<':' << one << endl; /////
}
else // 完成第 q 個字元,遞迴下一字元 q+1
{
if( rs[p+q]=='?' ) // 目前這個位置為 ? 偶則以 PBY各代1次、 奇則以 SCT各代1次
for(i=0; i<3; ++i)
{
c6[q] = ss[q%2][i]; setr(si, p, q+1);
}
else
{
c6[q] = rs[p+q]; setr(si, p, q+1);
}
}
}
string x,y,z; // 將nine切成3部份
int r; //共 r 個關係
bool ok() // 任一個關係 最少要有 某一列 3個巧克力 符合它
{
for(int si=0; si<r; ++si)
{
if( !( rel[si].find(x)!=rel[si].end() || rel[si].find(y)!=rel[si].end() || rel[si].find(z)!=rel[si].end() ) ) return false;
}
return true;
}
int main(void)
{
int i,j,k,t ,n;
char c;
c2n.clear();
c2n['P']=0; c2n['B']=3; c2n['Y']=6;
c2n['S']=1; c2n['C']=2; c2n['T']=3;
cin >> r;
for(i=0; i<r; ++i)
{
cin >> t;
for(j=0; j<t*2; ++j)
{
cin >> rs[j+2];/// >> rs[j+3];
}
/// cout << i <<':' << rs << endl; ////
if(t==3) setr(i,2,0); // 第i個關係,從第2字元、已轉了0個
else // t=2 , 前?? 及後 ?? 各一次
{
setr(i,0,0); // 第i個關係,從第0字元、已轉了0個
rs[6] = rs[7] ='?';
setr(i,2,0); // 第i個關係,從第2字元、已轉了0個
}
}
string nine="123456789";
// cout << nine << endl; 1~9 九位數,全排列 共 9! = 362880
int cnt=0;
do
{
x=nine.substr(0,3); y=nine.substr(3,3); z=nine.substr(6,3);
// cout << x <<',' << y <<',' << z <<'\n';
if( ok() ) ++cnt;
} while( next_permutation(nine.begin(),nine.end() ) );
cout << cnt << endl;
// system("pause");
return 0;
}
/*
3
3 B S Y S P C
3 P T B C Y T
3 P S B T Y C
3
3 B S Y ? ? C
2 B C Y T
3 P S ? ? Y C
==========
6
24
*/
2017年5月21日 星期日
vb版 BST建立及巡訪
一個TextBox1輸入5~30個皆不相同的整數以「,」隔開
一個Label1顯示輸出
一個按鈕,執行(1)建二元搜尋樹,(2)在Label1顯示{前序、中序、後序}巡訪結果
程式碼如下:
Public Class Form1
Class BT
Public data As Integer
Public lch As BT
Public rch As BT
Sub New()
lch = Nothing
rch = Nothing
End Sub
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim dat() = TextBox1.Text.Split(",") '依 , 分割為 陣列
Dim rt As BT = Nothing '一開始 樹根為 nothing
For i = 0 To UBound(dat)
Dim k As Integer = dat(i)
add(k, rt) '新增 1 node
Next
Dim s As String = "" : pre(s, rt) '前序
Label1.Text = "前序:" & s
s = "" : ino(s, rt) '中序
Label1.Text &= vbNewLine
Label1.Text &= "中序:" & s
s = "" : pos(s, rt) '後序
Label1.Text &= vbNewLine
Label1.Text &= "後序:" & s
End Sub
'將資料 k 新增至 樹根為 root 的 bst 樹中
Sub add(ByVal k As Integer, ByRef root As bt)
Dim node As New BT
node.data = k
If root Is Nothing Then
root = node
Return
End If
If k < root.data Then
add(k, root.lch)
Else
add(k, root.rch)
End If
End Sub
' 前序巡訪
Sub pre(ByRef s As String, ByVal node As bt)
If node Is Nothing Then Return
If s <> "" Then s &= ","
s &= node.data
pre(s, node.lch)
pre(s, node.rch)
End Sub
' 中序巡訪
Sub ino(ByRef s As String, ByVal node As bt)
If node Is Nothing Then Return
ino(s, node.lch)
If s <> "" Then s &= ","
s &= node.data
ino(s, node.rch)
End Sub
' 後序巡訪
Sub pos(ByRef s As String, ByVal node As bt)
If node Is Nothing Then Return
pos(s, node.lch)
pos(s, node.rch)
If s <> "" Then s &= ","
s &= node.data
End Sub
End Class
一個Label1顯示輸出
一個按鈕,執行(1)建二元搜尋樹,(2)在Label1顯示{前序、中序、後序}巡訪結果
程式碼如下:
Public Class Form1
Class BT
Public data As Integer
Public lch As BT
Public rch As BT
Sub New()
lch = Nothing
rch = Nothing
End Sub
End Class
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim dat() = TextBox1.Text.Split(",") '依 , 分割為 陣列
Dim rt As BT = Nothing '一開始 樹根為 nothing
For i = 0 To UBound(dat)
Dim k As Integer = dat(i)
add(k, rt) '新增 1 node
Next
Dim s As String = "" : pre(s, rt) '前序
Label1.Text = "前序:" & s
s = "" : ino(s, rt) '中序
Label1.Text &= vbNewLine
Label1.Text &= "中序:" & s
s = "" : pos(s, rt) '後序
Label1.Text &= vbNewLine
Label1.Text &= "後序:" & s
End Sub
'將資料 k 新增至 樹根為 root 的 bst 樹中
Sub add(ByVal k As Integer, ByRef root As bt)
Dim node As New BT
node.data = k
If root Is Nothing Then
root = node
Return
End If
If k < root.data Then
add(k, root.lch)
Else
add(k, root.rch)
End If
End Sub
' 前序巡訪
Sub pre(ByRef s As String, ByVal node As bt)
If node Is Nothing Then Return
If s <> "" Then s &= ","
s &= node.data
pre(s, node.lch)
pre(s, node.rch)
End Sub
' 中序巡訪
Sub ino(ByRef s As String, ByVal node As bt)
If node Is Nothing Then Return
ino(s, node.lch)
If s <> "" Then s &= ","
s &= node.data
ino(s, node.rch)
End Sub
' 後序巡訪
Sub pos(ByRef s As String, ByVal node As bt)
If node Is Nothing Then Return
pos(s, node.lch)
pos(s, node.rch)
If s <> "" Then s &= ","
s &= node.data
End Sub
End Class
2017年5月20日 星期六
b549 數位相片檔名
/*
b549 nr102-5 北二區102年-5 數位相片檔名
*/
#include <iostream>
#include <iomanip>
#include <set>
#include <map>
using namespace std;
map<int,int> used; // 已使用的 <時間 , 檔名>
map<int,int>::iterator mit;
map<int,int>::reverse_iterator rit;
bool can(int fn) // 傳入的檔名是否可用(符合雙遞增)
{
if(used.size()<2) return true; // 只有0或1個時,一定可以
int cnt=1; // 使用的 序列數,最多2個
mit=used.begin();
int fn1=mit->second, fn2=9999 ,fn3; //第1個使用 一個序列
// 若有兩個序列,維持 fn1<fn2
for(++mit; mit!=used.end() ; ++mit) // 從 第2個起與前一個比
{
fn3=mit->second; // 第2個起的檔案編號
if( fn3<fn1 )
{
if (cnt==2 ) return false; //已兩個再加1個 x
++cnt; fn2=fn1; fn1=fn3; //保持 fn1<fn2
}
else // fn3>fn1 可加入 fn1或fn2
{
if(fn3>fn2) fn2=fn3; //加至較大 的序列處,保留較小的序序編號
else fn1=fn3; // fn3<fn2無法加至 fn2,也保證 fn1=fn3<fn2
}
}
if( cnt==2 && fn<fn1 ) return false; //已兩個再加1個 x
else return true;
}
int main( )
{
int n , t ;
int fn[1000];
char c;
for( n=0; n<1000; ++n) fn[n] = n;
set <int>::iterator sit;
bool first=true;
while( cin >> n )
{
set <int> nuse(fn,fn+1000); //待用的檔號
used.clear();
while( n-- )
{
cin >> c >> t;
if( c == 'A' )
{
for( sit = nuse.begin(); sit != nuse.end(); ++sit )
{
int fn = *sit; //檢查檔名編號 fn 是否可用
if ( !can( fn ) ) continue; // 不能用,下一個
used[ t ] = fn; // t 時,加可用檔名 fn
nuse.erase( *sit );
break;
}
}
else
{
nuse.insert( used[t] ); // 未用的檔名,加一個
used.erase( t ); // 已用的 map <t,fn> 刪一個
}
}
// 印出,若不是第一組,則印出 --
if(first) first=false; else cout << "--\n";
rit = used.rbegin(); rit++; //先至倒數第2個
cout << "PIC" << setfill ('0') << setw (3) << (rit->second) << endl;
rit--;
cout << "PIC" << setfill ('0') << setw (3) << (rit->second) << endl;
}
return 0 ;
}
/* 輸入範例
10 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 4 A 6
14 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 4 A 6 D 3 A 7 D 0 A 8
14 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 D 0 A 8 A 9
14 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9
15 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9 A 10
17 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9 A 10 D 6 A 11
19 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9 A 10 D 6 A 11 D 11 A 12
9 A 0 A 1 A 2 A 3 D 2 A 4 D 1 D 0 A 5
9 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 A 6
10 A 0 A 1 A 2 A 3 A 4 D 2 A 5 A 6 D 3 A 7
輸出範例-----------------
PIC004
PIC001
--
PIC002
PIC003
--
PIC006
PIC007
--
PIC006
PIC001
--
PIC001
PIC002
--
PIC002
PIC004
--
PIC002
PIC004
--
PIC002
PIC004
--
PIC004
PIC005
--
PIC005
PIC003
*/
b549 nr102-5 北二區102年-5 數位相片檔名
*/
#include <iostream>
#include <iomanip>
#include <set>
#include <map>
using namespace std;
map<int,int> used; // 已使用的 <時間 , 檔名>
map<int,int>::iterator mit;
map<int,int>::reverse_iterator rit;
bool can(int fn) // 傳入的檔名是否可用(符合雙遞增)
{
if(used.size()<2) return true; // 只有0或1個時,一定可以
int cnt=1; // 使用的 序列數,最多2個
mit=used.begin();
int fn1=mit->second, fn2=9999 ,fn3; //第1個使用 一個序列
// 若有兩個序列,維持 fn1<fn2
for(++mit; mit!=used.end() ; ++mit) // 從 第2個起與前一個比
{
fn3=mit->second; // 第2個起的檔案編號
if( fn3<fn1 )
{
if (cnt==2 ) return false; //已兩個再加1個 x
++cnt; fn2=fn1; fn1=fn3; //保持 fn1<fn2
}
else // fn3>fn1 可加入 fn1或fn2
{
if(fn3>fn2) fn2=fn3; //加至較大 的序列處,保留較小的序序編號
else fn1=fn3; // fn3<fn2無法加至 fn2,也保證 fn1=fn3<fn2
}
}
if( cnt==2 && fn<fn1 ) return false; //已兩個再加1個 x
else return true;
}
int main( )
{
int n , t ;
int fn[1000];
char c;
for( n=0; n<1000; ++n) fn[n] = n;
set <int>::iterator sit;
bool first=true;
while( cin >> n )
{
set <int> nuse(fn,fn+1000); //待用的檔號
used.clear();
while( n-- )
{
cin >> c >> t;
if( c == 'A' )
{
for( sit = nuse.begin(); sit != nuse.end(); ++sit )
{
int fn = *sit; //檢查檔名編號 fn 是否可用
if ( !can( fn ) ) continue; // 不能用,下一個
used[ t ] = fn; // t 時,加可用檔名 fn
nuse.erase( *sit );
break;
}
}
else
{
nuse.insert( used[t] ); // 未用的檔名,加一個
used.erase( t ); // 已用的 map <t,fn> 刪一個
}
}
// 印出,若不是第一組,則印出 --
if(first) first=false; else cout << "--\n";
rit = used.rbegin(); rit++; //先至倒數第2個
cout << "PIC" << setfill ('0') << setw (3) << (rit->second) << endl;
rit--;
cout << "PIC" << setfill ('0') << setw (3) << (rit->second) << endl;
}
return 0 ;
}
/* 輸入範例
10 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 4 A 6
14 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 4 A 6 D 3 A 7 D 0 A 8
14 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 D 0 A 8 A 9
14 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9
15 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9 A 10
17 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9 A 10 D 6 A 11
19 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 D 5 A 6 A 7 A 8 D 4 A 9 A 10 D 6 A 11 D 11 A 12
9 A 0 A 1 A 2 A 3 D 2 A 4 D 1 D 0 A 5
9 A 0 A 1 A 2 A 3 D 2 A 4 D 1 A 5 A 6
10 A 0 A 1 A 2 A 3 A 4 D 2 A 5 A 6 D 3 A 7
輸出範例-----------------
PIC004
PIC001
--
PIC002
PIC003
--
PIC006
PIC007
--
PIC006
PIC001
--
PIC001
PIC002
--
PIC002
PIC004
--
PIC002
PIC004
--
PIC002
PIC004
--
PIC004
PIC005
--
PIC005
PIC003
*/
2017年5月2日 星期二
Z2A,Z1A求組合數
4/28中午及5/1晚上加強,Z2A三位、Z1A三位,共6位到課
Vb2010 -Windows Form專案: 四個按鈕、二個文字方塊(輸入m,n),一個標籤(輸出)
M取N求組合數(二項係數) 0<=N<=M<=66,分四種解法
程式碼如下:
Dim c(66, 66) As Long '第4種解法使用
'解法一:呼叫函式 pk(k) 算出 k階乘 值, 0<=k<=66 ,但k=21 時溢位
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
Label1.Text = pk(m) / pk(n) / pk(m - n)
End Sub
Function pk(ByVal k As Integer) As Long '函式
pk = 1
For i = 2 To k
pk *= i
Next
End Function
'解法二:先呼叫函式 pab(a,m):a*(a+1)*...*m , a=max(n,m-n)+1
' 再除函式 pk(min(n,m-n)) ,但也在 m=30時溢位
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
If n > m - n Then n = m - n
' 先算 a*...M , a是? 呼叫 pab(a,m)
Dim a As Integer = m - n + 1
'再除 pk(n)
Label1.Text = pab(a, m) / pk(n)
End Sub
Function pab(ByVal a As Integer, ByVal b As Integer) As Long
'a*a+1*a+2*...b
pab = 1
For i = a To b
pab *= i
Next
End Function
'解法三:純遞迴版呼叫 cmn(m,n)
' cmn(m,n)={0 for m=0, 1 for n=0 , cmn(m-1,n)+cmn(m-1,n-1) for other }
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
Dim t1 As Date = Now
Label1.Text = "純 C ( " & m & " , " & n & " ) = " & CMN(m, n) '呼叫純遞迴版
Label1.Text &= vbNewLine & DateDiff(DateInterval.Second, t1, Now) 'Cmn(29,14)約2秒,Cmn(30,15)約5秒
End Sub
Function CMN(ByVal m As Integer, ByVal n As Integer) As Long
If m = 0 Then Return 0
If n > m - n Then n = m - n '選 n, m-n 中較小的為 n
If n = 0 Then Return 1
c(m, n) = CMN(m - 1, n) + CMN(m - 1, n - 1)
Return c(m, n)
End Function
'解法四:動態規劃,建陣列C(66,66) 遞迴版呼叫 cmn2(m,n)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' vb宣告長整數 c(66,66) 初值預設為 0 , 另先設定 n=0時的初值為 1
For i = 0 To 66
c(i, 0) = 1
Next
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
Dim t1 As Date = Now
Label1.Text = "陣列 C ( " & m & " , " & n & " ) = " & CMN2(m, n) '呼叫陣列遞迴版
Label1.Text &= vbNewLine & DateDiff(DateInterval.Second, t1, Now) 'Cmn2(66,33)<1秒
End Sub
Function CMN2(ByVal m As Integer, ByVal n As Integer) As Long
If m = 0 Then Return 0 ' m=0傳回 0
If n > m - n Then n = m - n
If c(m, n) <> 0 Then Return c(m, n) '不為0 表示算過
c(m, n) = CMN2(m - 1, n) + CMN2(m - 1, n - 1)
Return c(m, n)
End Function
Vb2010 -Windows Form專案: 四個按鈕、二個文字方塊(輸入m,n),一個標籤(輸出)
M取N求組合數(二項係數) 0<=N<=M<=66,分四種解法
程式碼如下:
Dim c(66, 66) As Long '第4種解法使用
'解法一:呼叫函式 pk(k) 算出 k階乘 值, 0<=k<=66 ,但k=21 時溢位
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
Label1.Text = pk(m) / pk(n) / pk(m - n)
End Sub
Function pk(ByVal k As Integer) As Long '函式
pk = 1
For i = 2 To k
pk *= i
Next
End Function
'解法二:先呼叫函式 pab(a,m):a*(a+1)*...*m , a=max(n,m-n)+1
' 再除函式 pk(min(n,m-n)) ,但也在 m=30時溢位
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
If n > m - n Then n = m - n
' 先算 a*...M , a是? 呼叫 pab(a,m)
Dim a As Integer = m - n + 1
'再除 pk(n)
Label1.Text = pab(a, m) / pk(n)
End Sub
Function pab(ByVal a As Integer, ByVal b As Integer) As Long
'a*a+1*a+2*...b
pab = 1
For i = a To b
pab *= i
Next
End Function
'解法三:純遞迴版呼叫 cmn(m,n)
' cmn(m,n)={0 for m=0, 1 for n=0 , cmn(m-1,n)+cmn(m-1,n-1) for other }
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
Dim t1 As Date = Now
Label1.Text = "純 C ( " & m & " , " & n & " ) = " & CMN(m, n) '呼叫純遞迴版
Label1.Text &= vbNewLine & DateDiff(DateInterval.Second, t1, Now) 'Cmn(29,14)約2秒,Cmn(30,15)約5秒
End Sub
Function CMN(ByVal m As Integer, ByVal n As Integer) As Long
If m = 0 Then Return 0
If n > m - n Then n = m - n '選 n, m-n 中較小的為 n
If n = 0 Then Return 1
c(m, n) = CMN(m - 1, n) + CMN(m - 1, n - 1)
Return c(m, n)
End Function
'解法四:動態規劃,建陣列C(66,66) 遞迴版呼叫 cmn2(m,n)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' vb宣告長整數 c(66,66) 初值預設為 0 , 另先設定 n=0時的初值為 1
For i = 0 To 66
c(i, 0) = 1
Next
End Sub
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Dim m As Integer = TextBox1.Text
Dim n As Integer = TextBox2.Text
Dim t1 As Date = Now
Label1.Text = "陣列 C ( " & m & " , " & n & " ) = " & CMN2(m, n) '呼叫陣列遞迴版
Label1.Text &= vbNewLine & DateDiff(DateInterval.Second, t1, Now) 'Cmn2(66,33)<1秒
End Sub
Function CMN2(ByVal m As Integer, ByVal n As Integer) As Long
If m = 0 Then Return 0 ' m=0傳回 0
If n > m - n Then n = m - n
If c(m, n) <> 0 Then Return c(m, n) '不為0 表示算過
c(m, n) = CMN2(m - 1, n) + CMN2(m - 1, n - 1)
Return c(m, n)
End Function
Z2A河內塔範例
4/26中午加強,Z2A三位學生到課
Vb2010 -Windows Form專案: 一個按鈕、一個文字方塊,以debug.print輸出至即時運算視窗
程式碼如下:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim n As Integer = TextBox1.Text
ho(n, "A", "B", "C")
End Sub
Sub ho(ByVal n As Integer, ByVal a As Char, ByVal b As Char, ByVal c As Char)
If n = 1 Then
Debug.Print(n & ":" & a & c)
Return
End If
ho(n - 1, a, c, b)
Debug.Print(n & ":" & a & c)
ho(n - 1, b, a, c)
End Sub
輸出範例:
輸入 4 的輸出如下
1:AB
2:AC
1:BC
3:AB
1:CA
2:CB
1:AB
4:AC
1:BC
2:BA
1:CA
3:BC
1:AB
2:AC
1:BC
輸入 5 的輸出如下
1:AC
2:AB
1:CB
3:AC
1:BA
2:BC
1:AC
4:AB
1:CB
2:CA
1:BA
3:CB
1:AC
2:AB
1:CB
5:AC
1:BA
2:BC
1:AC
3:BA
1:CB
2:CA
1:BA
4:BC
1:AC
2:AB
1:CB
3:AC
1:BA
2:BC
1:AC
Vb2010 -Windows Form專案: 一個按鈕、一個文字方塊,以debug.print輸出至即時運算視窗
程式碼如下:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim n As Integer = TextBox1.Text
ho(n, "A", "B", "C")
End Sub
Sub ho(ByVal n As Integer, ByVal a As Char, ByVal b As Char, ByVal c As Char)
If n = 1 Then
Debug.Print(n & ":" & a & c)
Return
End If
ho(n - 1, a, c, b)
Debug.Print(n & ":" & a & c)
ho(n - 1, b, a, c)
End Sub
輸出範例:
輸入 4 的輸出如下
1:AB
2:AC
1:BC
3:AB
1:CA
2:CB
1:AB
4:AC
1:BC
2:BA
1:CA
3:BC
1:AB
2:AC
1:BC
1:AC
2:AB
1:CB
3:AC
1:BA
2:BC
1:AC
4:AB
1:CB
2:CA
1:BA
3:CB
1:AC
2:AB
1:CB
5:AC
1:BA
2:BC
1:AC
3:BA
1:CB
2:CA
1:BA
4:BC
1:AC
2:AB
1:CB
3:AC
1:BA
2:BC
1:AC