1. 程式人生 > >於航特訓課第二課

於航特訓課第二課

con 振興中華 簡介 integer 符號 else 跳過 pro OS

藍橋杯算法特訓第二課【遞歸原理與構造技巧】源代碼

三月 7, 2018小藍 技術分享圖片

【內容簡介】
本文章內容為【2018藍橋杯大賽算法特訓(軟件)系列課程】第二課【遞歸原理與構造技巧】中涉及到的課上例題的代碼實現,加入賽前算法特訓獲取全部課程內容請聯系【小藍】。


【課程中涉及的源代碼】
1. 串的翻轉
【問題描述】
【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
public class A
{
static String f(String s){
if(s.length()<=1) return s;
return f(s.substring(1)) + s.charAt(0);
}

public static void main(String[] args){
System.out.println(f("abcde"));
}
}

【C:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

char * f(char * s, int num)
{
if (num <= 1)
{
return s;
}
else
{
char *p = (char *)malloc(num+1);
memset(p, 0, num+1);
strcpy(p, s+1);
char *pp = f(p, num-1);
strcpy(p, pp);
if (p!=pp)
free(pp);
strncpy(p+num-1,s,1);
return p;
}
}

void main()
{
char arr[100] = "abcde";
printf("%s", f(arr, 5));

}


2. 循環改遞歸
【問題描述】
【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class A
{
static void f(int a, int b){
for(int i=a; i<=b; i++){
System.out.println(i);
}
}

static void g(int a, int b){
if(a<b) g(a,b-1);
System.out.println(b);
}

public static void main(String[] args){
//f(1,10);
g(1,10);
}
}

【C語言:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

void f2(int a, int b)
{
for (int i = a; i <= b; i++){
printf("%d ",i);
}
}

void g2(int a, int b)
{
if (a < b)
g2(a, b - 1);
printf("%d ",b);
}

void main()
{
//f2(1,10);
g2(1, 10);
}


3. 出棧次序
【問題描述】
X星球特別講究秩序,所有道路都是單行線。
一個甲殼蟲車隊,共16輛車,按照編號先後發車,夾在其它車流中,緩緩前行。
路邊有個死胡同,只能容一輛車通過,是臨時的檢查站,如圖所示。
技術分享圖片
X星球太死板,要求每輛路過的車必須進入檢查站,也可能不檢查就放行,也可能仔細檢查。
如果車輛進入檢查站和離開的次序可以任意交錯。那麽,該車隊再次上路後,可能的次序有多少種?
為了方便起見,假設檢查站可容納任意數量的汽車。
顯然,如果車隊只有1輛車,可能次序1種;2輛車可能次序2種;3輛車可能次序5種。
【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/*
如果進棧次序為:1 2 3 4 5 。。。
出棧次序有多少種情況?

*/

public class A
{
// n 個等著進棧,棧中有m個
static int f(int n, int m)
{
if(n==0) return 1;
if(m==0) return f(n-1,1);
return f(n,m-1) + f(n-1, m+1);
}

static int f(int n)
{
return f(n, 0);
}

public static void main(String[] args)
{
for(int i=1; i<17; i++){
System.out.println(i + ": " + f(i));
}
}
}

【C語言:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define _CRT_SECURE_NO_WARNINGS
#include
#include
/*
如果進棧次序為:1 2 3 4 5 。。。
出棧次序有多少種情況?

*/

// n 個等著進棧,棧中有m個
int f3(int n, int m)
{
if (n == 0)
return 1;
if (m == 0)
return f3(n - 1, 1);
return
f3(n, m - 1) + f3(n - 1, m + 1);
}

int f5(int n)
{
return f3(n, 0);
}

void main()
{
for (int i = 1; i<17; i++)
{
printf("%d : %d \n", i, f5(i));
}
}


4. 第39級臺階
【問題描述】

小明剛剛看完電影《第39級臺階》。離開電影院的時候,他數了數禮堂前的臺階數,恰好是39級!
站在臺階前,他突然又想著一個問題:
如果我每一步只能邁上1個或2個臺階。先邁左腳,然後左右交替,最後一步是邁右腳,也就是說一共要走偶數步。那麽,上完39級臺階,有多少種不同的上法呢?
請你利用計算機的優勢,幫助小明尋找答案。

【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class A
{
// 奇數步
static long g(int n)
{
if(n==0) return 0;
if(n==1) return 1;
//if(n==2) return 1;

return f(n-1) + f(n-2);
}

// 偶數步
static long f(int n)
{
if(n==0) return 1;
if(n==1) return 0;
//if(n==2) return 1;

return g(n-1) + g(n-2);
}

public static void main(String[] args)
{
System.out.println(f(5));
System.out.println(f(39));
}
}

【C語言:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

long ff(int n);
// 奇數步
long gg(int n)
{
if (n == 0)
return 0;
if (n == 1)
return 1;
/*if(n==2)
return 1;*/
return ff(n - 1) + ff(n - 2);
}

// 偶數步
long ff(int n)
{
if (n == 0)
return 1;
if (n == 1)
return 0;
/*if(n==2)
return 1;*/
return gg(n - 1) + gg(n - 2);
}

void main()
{
printf("%d \n",ff(5));
printf("%d ", ff(39));
}

5. 算式填符號
【問題描述】

匪警請撥110,即使手機欠費也可撥通!
為了保障社會秩序,保護人民群眾生命財產安全,警察叔叔需要與罪犯鬥智鬥勇,因而需要經常性地進行體力訓練和智力訓練!

某批警察叔叔正在進行智力訓練:
1 2 3 4 5 6 7 8 9 = 110

請看上邊的算式,為了使等式成立,需要在數字間填入加號或者減號(可以不填,但不能填入其它符號)。之間沒有填入符號的數字組合成一個數,例如:12+34+56+7-8+9 就是一種合格的填法;123+4+5+67-89 是另一個可能的答案。

請你利用計算機的優勢,幫助警察叔叔快速找到所有答案。
每個答案占一行。形如:
12+34+56+7-8+9
123+4+5+67-89
……

【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class SuanShi
{
//a: 參加計算的元素
//k: 目前考慮的元素下標
//so: 合成好的結果串
//goal: 計算目標
static void f(int[] a, int k, String so, int goal){
if(k==0){
if(a[0] == goal){
System.out.println(a[0]+so);
}
return;
}

f(a,k-1,"+"+a[k]+so, goal-a[k]);
f(a,k-1,"-"+a[k]+so, goal+a[k]);
int old = a[k-1];
a[k-1] = Integer.parseInt("" + a[k-1] + a[k]);
f(a,k-1,so,goal);
a[k-1] = old;
}

public static void main(String[] args){
int[] a = {1,2,3,4,5,6,7,8,9};
f(a,8,"",110);
}
}

【C語言:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include

//a: 參加計算的元素
//k: 目前考慮的元素下標
//so: 合成好的結果串
//goal: char
void fk(int *a, int k, char *s, int goal){
if (k == 0){
if (a[0] == goal){
printf("%d%s\n",a[0],s);
}
return;
}

char * p = malloc(k * 2 + 1);
memset(p, 0, k * 2 + 1);

p[0] = ‘+‘;
_itoa(a[k], p+1, 10);
int x = strlen(p);
strcat(p+x, s);
fk(a, k - 1, p, goal - a[k]);

p[0] = ‘-‘;
fk(a, k - 1, p, goal + a[k]);


int old = a[k - 1];
char ak[1024] = { 0 };
char ak2[1024] = { 0 };
_itoa(a[k - 1], ak, 10);
_itoa(a[k], ak2, 10);
strcat(ak, ak2);
a[k - 1] = atoi(ak);
memset(p, 0, k * 2 + 1);
strcat(p, s);
fk(a, k - 1, p, goal);
a[k - 1] = old;
}



void main()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
fk(a, 8, "", 110);
}


6. 找錢問題
【問題描述】

公園票價為5角。假設每位遊客只持有兩種幣值的貨幣:5角、1元。
再假設持有5角的有m人,持有1元的有n人。
由於特殊情況,開始的時候,售票員沒有零錢可找。
我們想知道這m+n名遊客以什麽樣的順序購票則可以順利完成購票過程。
顯然,m < n的時候,無論如何都不能完成;
m>=n的時候,有些情況也不行。比如,第一個購票的乘客就持有1元。
請計算出這m+n名遊客所有可能順利完成購票的不同情況的組合數目。
註意:只關心5角和1元交替出現的次序的不同排列,持有同樣幣值的兩名遊客交換位置並不算做一種新的情況來計數。

【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//考慮最後一個人
public class ZhaoQian1
{
//m: 持有5角的
//n: 持有1元的
static int f(int m, int n){
if(m&lt;n) return 0;
if(m==1) return 1;
if(n==0) return 1;

return f(m-1,n) + f(m,n-1);
}

public static void main(String[] args){
System.out.println(f(2,2));
System.out.println(f(3,2));
System.out.println(f(5,3));
}
}

//考慮第一個人
public class ZhaoQian2
{
//m: 持有5角的
//n: 持有1元的
//t: 售票員手裏有多少個5角的
static int f(int m, int n, int t){
if(m+t&lt;n) return 0; if(m==0) return 1; if(n==0) return 1; int r = f(m-1,n,t+1); if(t&gt;0) r += f(m,n-1,t-1);
return r;
}

public static void main(String[] args){
System.out.println(f(2,2,0));
System.out.println(f(3,2,0));
System.out.println(f(5,3,0));
}
}

【C語言:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
//考慮最後一個人
//m: 持有5角的
//n: 持有1元的
int f6(int m, int n)
{
if (m &lt; n)
return 0;
if (m == 1)
return 1;
if (n == 0)
return 1;

return f6(m - 1, n) + f6(m, n - 1);
}

void main(){
printf("%d \n",f6(2, 2));
printf("%d \n",f6(3, 2));
printf("%d \n",f6(5, 3));

}

//==========================================

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
//考慮第一個人
//m: 持有5角的
//n: 持有1元的
//t: 售票員手裏有多少個5角的
int fn(int m, int n, int t)
{
if (m + t&lt;n) return 0; if (m == 0) return 1; if (n == 0) return 1; int r = fn(m - 1, n, t + 1); if (t&gt;0)
r += fn(m, n - 1, t - 1);
return r;
}

void main()
{
printf("%d \n", fn(2, 2, 0));
printf("%d \n", fn(3, 2, 0));
printf("%d \n", fn(5, 3, 0));

}

7. 振興中華
【問題描述】
小明參加了學校的趣味運動會,其中的一個項目是:跳格子。
地上畫著一些格子,每個格子裏寫一個字,如下所示:(也可參見下圖)

從我做起振
我做起振興
做起振興中
起振興中華
技術分享圖片
比賽時,先站在左上角的寫著“從”字的格子裏,可以橫向或縱向跳到相鄰的格子裏,但不能跳到對角的格子或其它位置。一直要跳到“華”字結束。

要求跳過的路線剛好構成“從我做起振興中華”這句話。
請你幫助小明算一算他一共有多少種可能的跳躍路線呢?

【源代碼】
【JAVA:於航】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class A
{
static int f(int m, int n)
{
if(m==1 || n==1) return 1;

return f(m-1,n) + f(m,n-1);
}

public static void main(String[] args)
{
System.out.println(f(5,4));
//System.out.println(f(3,2));
}

}

【C語言:誌願者】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
int f7(int m, int n)
{
if (m == 1 || n == 1)
return 1;
return f7(m - 1, n) + f7(m, n - 1);
}

void main7()
{
printf("%d \n", f7(5, 4));
//printf("%d \n", f7(3, 2));
}

於航特訓課第二課