日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

蓝桥杯C++ AB组辅导课 第一讲 递归与递推 Acwing

發(fā)布時(shí)間:2025/3/19 c/c++ 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝桥杯C++ AB组辅导课 第一讲 递归与递推 Acwing 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

例題

AcWing 92. 遞歸實(shí)現(xiàn)指數(shù)型枚舉

從 1~n 這 n 個(gè)整數(shù)中隨機(jī)選取任意多個(gè),輸出所有可能的選擇方案。

輸入格式
輸入一個(gè)整數(shù) n。

輸出格式
每行輸出一種方案。

同一行內(nèi)的數(shù)必須升序排列,相鄰兩個(gè)數(shù)用恰好 1 個(gè)空格隔開(kāi)。

對(duì)于沒(méi)有選任何數(shù)的方案,輸出空行。

本題有自定義校驗(yàn)器(SPJ),各行(不同方案)之間的順序任意。

數(shù)據(jù)范圍

1≤n≤15

輸入樣例:

3

輸出樣例:

3 2 2 3 1 1 3 1 2 1 2 3

思路 :

  • 實(shí)際上每個(gè)數(shù)只要考慮選(1)和不選(2)這兩個(gè)狀態(tài),也就是說(shuō)回溯回來(lái)不需要恢復(fù)成0,相當(dāng)于每個(gè)結(jié)點(diǎn)有兩個(gè)分叉,所以是 2n2^n2n 指數(shù)型枚舉
  • dfs時(shí),結(jié)束遞歸時(shí)一定要return
#include <iostream> using namespace std;const int N = 16;int n; int st[N]; // 0表示還沒(méi)考慮 1表示選 2表示不選void dfs(int u) {if (u > n){for (int i = 1; i <= n; i ++ )if (st[i] == 1)printf("%d ", i);puts("");return ;}st[u] = 2;dfs(u + 1);// st[u] = 0;st[u] = 1;dfs(u + 1);// st[u] = 0; }int main() {scanf("%d", &n);dfs(1);return 0; }

AcWing 94. 遞歸實(shí)現(xiàn)排列型枚舉

把 1~n 這 n 個(gè)整數(shù)排成一行后隨機(jī)打亂順序,輸出所有可能的次序。

輸入格式
一個(gè)整數(shù) n。

輸出格式
按照從小到大的順序輸出所有方案,每行 1 個(gè)。

首先,同一行相鄰兩個(gè)數(shù)用一個(gè)空格隔開(kāi)。

其次,對(duì)于兩個(gè)不同的行,對(duì)應(yīng)下標(biāo)的數(shù)一一比較,字典序較小的排在前面。

數(shù)據(jù)范圍

1≤n≤9

輸入樣例:

3

輸出樣例:

1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1

思路 :

  • n?(n?1)?...?1n*(n-1)*...*1n?(n?1)?...?1種排列方式,因此是排列型枚舉
  • 每次遞歸決定當(dāng)前這個(gè)盒子中放什么數(shù)字,由于不重復(fù)放,因此開(kāi)一個(gè)數(shù)組記錄當(dāng)前是否用過(guò)這個(gè)數(shù)字,因此回溯要恢復(fù)現(xiàn)場(chǎng)
#include <iostream> using namespace std;const int N = 10;int n; int state[N]; bool st[N];void dfs(int u) {if (u > n){for (int i = 1; i <= n; i ++ )printf("%d ", state[i]);puts("");return ;}for (int i = 1; i <= n; i ++ ){if (!st[i]){st[i] = true;state[u] = i;dfs(u + 1);// state[u] = 0;st[i] = false;}} }int main() {scanf("%d", &n);dfs(1);return 0; }

AcWing 717. 簡(jiǎn)單斐波那契

以下數(shù)列 0 1 1 2 3 5 8 13 21 … 被稱為斐波納契數(shù)列。

這個(gè)數(shù)列從第 3 項(xiàng)開(kāi)始,每一項(xiàng)都等于前兩項(xiàng)之和。

輸入一個(gè)整數(shù) N,請(qǐng)你輸出這個(gè)序列的前 N 項(xiàng)。

輸入格式
一個(gè)整數(shù) N。

輸出格式
在一行中輸出斐波那契數(shù)列的前 N 項(xiàng),數(shù)字之間用空格隔開(kāi)。

數(shù)據(jù)范圍

0<N<46

輸入樣例:

5

輸出樣例:

0 1 1 2 3 // 遞推 #include <iostream> using namespace std;int main() {int n; scanf("%d", &n);int a = 0, b = 1, c;for (int i = 0; i < n; i ++ ){printf("%d ", a);c = a + b, a = b, b = c;} } #include <iostream> using namespace std;const int N = 47;int n; int f[N];int dfs(int u) {if (u == 1 || u == 2 || f[u]) return f[u];return f[u] = dfs(u - 1) + dfs(u - 2); }int main() {scanf("%d", &n);f[1] = 0, f[2] = 1;dfs(n);for (int i = 1; i <= n; i ++ ) cout << f[i] << ' ' ;return 0; }

AcWing 95. 費(fèi)解的開(kāi)關(guān)

你玩過(guò)“拉燈”游戲嗎?

25 盞燈排成一個(gè) 5×5 的方形。

每一個(gè)燈都有一個(gè)開(kāi)關(guān),游戲者可以改變它的狀態(tài)。

每一步,游戲者可以改變某一個(gè)燈的狀態(tài)。

游戲者改變一個(gè)燈的狀態(tài)會(huì)產(chǎn)生連鎖反應(yīng):和這個(gè)燈上下左右相鄰的燈也要相應(yīng)地改變其狀態(tài)。

我們用數(shù)字 1 表示一盞開(kāi)著的燈,用數(shù)字 0 表示關(guān)著的燈。

下面這種狀態(tài)

10111
01101
10111
10000
11011
在改變了最左上角的燈的狀態(tài)后將變成:

01111
11101
10111
10000
11011
再改變它正中間的燈后狀態(tài)將變成:

01111
11001
11001
10100
11011
給定一些游戲的初始狀態(tài),編寫程序判斷游戲者是否可能在 6 步以內(nèi)使所有的燈都變亮。

輸入格式
第一行輸入正整數(shù) n,代表數(shù)據(jù)中共有 n 個(gè)待解決的游戲初始狀態(tài)。

以下若干行數(shù)據(jù)分為 n 組,每組數(shù)據(jù)有 5 行,每行 5 個(gè)字符。

每組數(shù)據(jù)描述了一個(gè)游戲的初始狀態(tài)。

各組數(shù)據(jù)間用一個(gè)空行分隔。

輸出格式
一共輸出 n 行數(shù)據(jù),每行有一個(gè)小于等于 6 的整數(shù),它表示對(duì)于輸入數(shù)據(jù)中對(duì)應(yīng)的游戲狀態(tài)最少需要幾步才能使所有燈變亮。

對(duì)于某一個(gè)游戲初始狀態(tài),若 6 步以內(nèi)無(wú)法使所有燈變亮,則輸出 ?1。

數(shù)據(jù)范圍

0<n≤500

輸入樣例:

3 00111 01011 10001 11010 1110011101 11101 11110 11111 1111101111 11111 11111 11111 11111

輸出樣例:

3 2 -1

思路 :

  • 目標(biāo)是把所有開(kāi)關(guān)全部變成1,由于當(dāng)上一行的狀態(tài)確定時(shí),若上一行存在0的狀態(tài),只能由下一行的位置影響上一行的0(注意這是四連通),因此可以使用遞推
  • 只要第0行開(kāi)關(guān)狀態(tài)確定,則所有開(kāi)關(guān)的狀態(tài)都可以遞推出來(lái),因此只要枚舉第一行狀態(tài)的所有情況,有252^525
  • 從第0行遞推出第1到第4行的所有狀態(tài),若當(dāng)前行狀態(tài)已確定,且存在開(kāi)關(guān)是0狀態(tài)的,則需要下一行的位置對(duì)開(kāi)關(guān)進(jìn)行切換,影響當(dāng)前行開(kāi)關(guān)是0的狀態(tài)
  • 最后枚舉最后一行,若該狀態(tài)全部是1,則表示成功,更新最小步數(shù)

語(yǔ)法 :

  • char二維數(shù)組的輸入方式
  • 第一行一共32種狀態(tài),也就是[0,31][0,31][0,31],op >> i & 1
  • 每種枚舉方式中,一開(kāi)始用backup備份g,最后再備份回來(lái)
  • 如果res大于6,直接賦值為-1
  • 即使g二維數(shù)組是char類型,但可以g[a][b]^=1,0變成1,1變成0
#include <iostream> #include <cstring> using namespace std;const int N = 6;char g[N][N], backup[N][N]; int dx[5] = {0, 1, 0, -1, 0}, dy[5] = {1, 0, -1, 0, 0};void turn(int x, int y) {for (int i = 0; i < 5; i ++ ){int a = x + dx[i], b = y + dy[i];if (a < 0 || a > 4 || b < 0 || b > 4) continue;g[a][b] ^= 1;} }int main() {int _; scanf("%d", &_);while (_ -- ){for (int i = 0; i < 5; i ++ ) cin >> g[i];int res = 10;for (int op = 0; op < 32; op ++ ){memcpy(backup, g, sizeof g);int step = 0;for (int i = 0; i < 5; i ++ )if (op >> i & 1){step ++ ;turn(0, i);}for (int i = 0; i < 4; i ++ )for (int j =0 ; j < 5; j ++ )if (g[i][j] == '0'){step ++ ;turn(i + 1, j);}bool dark = false;for (int i = 0; i < 5; i ++ )if (g[4][i] == '0'){dark = true;break;}if (!dark) res = min(res, step);memcpy(g, backup, sizeof backup);}if (res > 6) res = -1;printf("%d\n", res);} }

習(xí)題

AcWing 93. 遞歸實(shí)現(xiàn)組合型枚舉

從 1~n 這 n 個(gè)整數(shù)中隨機(jī)選出 m 個(gè),輸出所有可能的選擇方案。

輸入格式
兩個(gè)整數(shù) n,m ,在同一行用空格隔開(kāi)。

輸出格式
按照從小到大的順序輸出所有方案,每行 1 個(gè)。

首先,同一行內(nèi)的數(shù)升序排列,相鄰兩個(gè)數(shù)用一個(gè)空格隔開(kāi)。

其次,對(duì)于兩個(gè)不同的行,對(duì)應(yīng)下標(biāo)的數(shù)一一比較,字典序較小的排在前面(例如 1 3 5 7 排在 1 3 6 8 前面)。

數(shù)據(jù)范圍

n>0 , 0≤m≤n , n+(n?m)25

輸入樣例:

5 3

輸出樣例:

1 2 3 1 2 4 1 2 5 1 3 4 1 3 5 1 4 5 2 3 4 2 3 5 2 4 5 3 4 5

思考題:如果要求使用非遞歸方法,該怎么做呢?

思路 :

  • dfs第一個(gè)參數(shù)為當(dāng)前放到第i個(gè)位置(一共m個(gè)),第二個(gè)參數(shù)為這一次開(kāi)始選擇的數(shù)字(比上一次的大)
  • 枚舉邊界為放到第m+1個(gè)位置,也就是說(shuō)放完了
  • 剪枝,加上后面放的數(shù)不足m個(gè)
#include <iostream> using namespace std;const int N = 30;int n, m; int state[N];void dfs(int u, int start) {if (u + n - start < m) return ;if (u == m + 1){for (int i = 1; i <= m; i ++ )cout << state[i] << ' ';cout << endl;return ;}for (int i = start; i <= n; i ++ ){state[u] = i;dfs(u + 1, i + 1);} }int main() {cin >> n >> m;dfs(1, 1);return 0; }

AcWing 1209. 帶分?jǐn)?shù)

100 可以表示為帶分?jǐn)?shù)的形式:100=3+69258714
還可以表示為:100=82+3546197
注意特征:帶分?jǐn)?shù)中,數(shù)字 1~9 分別出現(xiàn)且只出現(xiàn)一次(不包含 0)。

類似這樣的帶分?jǐn)?shù),100 有 11 種表示法。

輸入格式
一個(gè)正整數(shù)。

輸出格式
輸出輸入數(shù)字用數(shù)碼 1~9 不重復(fù)不遺漏地組成帶分?jǐn)?shù)表示的全部種數(shù)。

數(shù)據(jù)范圍

1≤N<106

輸入樣例1:

100

輸出樣例1:

11

輸入樣例2:

105

輸出樣例2:

6

思路 :

  • 給一個(gè)數(shù)n,問(wèn)有多少組a+bc=na+\frac{b}{c}=na+cb?=n,且abc三個(gè)數(shù)不重不漏地涵蓋1-9這9個(gè)數(shù)字
  • 暴力枚舉9個(gè)數(shù)的全排列,然后用一個(gè)長(zhǎng)度為9的數(shù)組保存全排列的結(jié)果
  • 從全排列的結(jié)果中用兩重循環(huán)暴力分解出三段,每段代表一個(gè)數(shù)
  • 驗(yàn)證枚舉出的三個(gè)數(shù)是否滿足題干條件,若滿足則計(jì)數(shù)
#include <iostream> using namespace std;int n, cnt; bool st[10]; int state[10];int calc(int l, int r) {int res = 0;for (int i = l; i <= r; i ++ )res = res * 10 + state[i];return res; }void dfs(int u) {if (u == 10){for (int i = 1; i < 10; i ++ )for (int j = i + 1; j < 9; j ++ ){int a = calc(1, i);int b = calc(i + 1, j);int c = calc(j + 1, 9);if (a * c + b == n * c) cnt ++ ;}return ;}for (int i = 1; i <= 9; i ++ )if (!st[i]){state[u] = i;st[i] = true;dfs(u + 1);st[i] = false;} }int main() {cin >> n;dfs(1);cout << cnt << endl;return 0; }

AcWing 116. 飛行員兄弟

“飛行員兄弟”這個(gè)游戲,需要玩家順利的打開(kāi)一個(gè)擁有 16 個(gè)把手的冰箱。

已知每個(gè)把手可以處于以下兩種狀態(tài)之一:打開(kāi)或關(guān)閉。

只有當(dāng)所有把手都打開(kāi)時(shí),冰箱才會(huì)打開(kāi)。

把手可以表示為一個(gè) 4×4 的矩陣,您可以改變?nèi)魏我粋€(gè)位置 [i,j] 上把手的狀態(tài)。

但是,這也會(huì)使得第 i 行和第 j 列上的所有把手的狀態(tài)也隨著改變。

請(qǐng)你求出打開(kāi)冰箱所需的切換把手的次數(shù)最小值是多少。

輸入格式
輸入一共包含四行,每行包含四個(gè)把手的初始狀態(tài)。

符號(hào) + 表示把手處于閉合狀態(tài),而符號(hào) - 表示把手處于打開(kāi)狀態(tài)。

至少一個(gè)手柄的初始狀態(tài)是關(guān)閉的。

輸出格式
第一行輸出一個(gè)整數(shù) N,表示所需的最小切換把手次數(shù)。

接下來(lái) N 行描述切換順序,每行輸出兩個(gè)整數(shù),代表被切換狀態(tài)的把手的行號(hào)和列號(hào),數(shù)字之間用空格隔開(kāi)。

注意:如果存在多種打開(kāi)冰箱的方式,則按照優(yōu)先級(jí)整體從上到下,同行從左到右打開(kāi)。

數(shù)據(jù)范圍

1≤i,j≤4

輸入樣例:

-+-- ---- ---- -+--

輸出樣例:

6 1 1 1 3 1 4 4 1 4 3 4 4

思路 :

  • 本題比較特殊,可以用代碼把所有情況枚舉一遍,會(huì)發(fā)現(xiàn)每種局面的操作方案是唯一的,所以第一次找到的解一定是最優(yōu)解。
  • 216?16?162^{16}*16*16216?16?16
#include <iostream> #include <cstring> #include <vector> using namespace std;typedef pair<int, int> PII;char g[4][4], backup[4][4];int get(int x, int y) {return x * 4 + y; }void turn_one(int x, int y) {if (g[x][y] == '+') g[x][y] = '-';else g[x][y] = '+'; }void turn_all(int x, int y) {for (int i = 0; i < 4; i ++ ){turn_one(x, i);turn_one(i, y);}turn_one(x, y); }int main() {for (int i = 0; i < 4; i ++ ) cin >> g[i];vector<PII> res;for (int op = 0; op < (1 << 16); op ++ ){memcpy(backup, g, sizeof backup);vector<PII> temp;for (int i = 0; i < 4; i ++ )for (int j = 0; j < 4; j ++ )if (op >> get(i, j) & 1){turn_all(i, j);temp.push_back({i, j});}bool has_closed = false;for (int i = 0; i < 4; i ++ )for (int j = 0; j < 4; j ++ )if (g[i][j] == '+')has_closed = true;if (has_closed == false){if (res.empty() || res.size() > temp.size()) res = temp;}memcpy(g, backup, sizeof backup);}cout << res.size() << endl;for (auto op : res) cout << op.first + 1 << ' ' << op.second + 1 << endl; }

AcWing 1208. 翻硬幣

小明正在玩一個(gè)“翻硬幣”的游戲。

桌上放著排成一排的若干硬幣。我們用 * 表示正面,用 o 表示反面(是小寫字母,不是零)。

比如,可能情形是:oo*oooo

如果同時(shí)翻轉(zhuǎn)左邊的兩個(gè)硬幣,則變?yōu)?#xff1a;oooo***oooo

現(xiàn)在小明的問(wèn)題是:如果已知了初始狀態(tài)和要達(dá)到的目標(biāo)狀態(tài),每次只能同時(shí)翻轉(zhuǎn)相鄰的兩個(gè)硬幣,那么對(duì)特定的局面,最少要翻動(dòng)多少次呢?

我們約定:把翻動(dòng)相鄰的兩個(gè)硬幣叫做一步操作。

輸入格式
兩行等長(zhǎng)的字符串,分別表示初始狀態(tài)和要達(dá)到的目標(biāo)狀態(tài)。

輸出格式
一個(gè)整數(shù),表示最小操作步數(shù)

數(shù)據(jù)范圍
輸入字符串的長(zhǎng)度均不超過(guò)100。
數(shù)據(jù)保證答案一定有解。

輸入樣例1:

********** o****o****

輸出樣例1:

5

輸入樣例2:

*o**o***o*** *o***o**o***

輸出樣例2:

1

思路 :

  • 規(guī)則是每次翻轉(zhuǎn)兩個(gè)相鄰的硬幣,一個(gè)硬幣要翻轉(zhuǎn)必會(huì)使左右兩邊其中一個(gè)受到牽連,因此可以貪心單一方向進(jìn)行牽連,就不會(huì)使之前翻好的硬幣重新翻轉(zhuǎn)
#include <iostream> #include <cstring> using namespace std;const int N = 110;int n; char s1[N], s2[N];void turn(int i) {if (s1[i] == '*') s1[i] = 'o';else s1[i] = '*'; }int main() {cin >> s1 >> s2;n = strlen(s1);int res = 0;for (int i = 0; i < n; i ++ )if (s1[i] != s2[i]){turn(i), turn(i + 1);res ++ ;}cout << res << endl; }

總結(jié)

以上是生活随笔為你收集整理的蓝桥杯C++ AB组辅导课 第一讲 递归与递推 Acwing的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美色图亚洲激情 | 欧美久久视频 | 伊人久综合 | 麻豆视频国产精品 | 欧美性一级片 | 综合狠狠开心 | 黑人巨大猛烈捣出白浆 | 亚洲男人天堂网站 | 777av| 99热网址| 日韩在线精品视频 | 久久香蕉网 | 日本黄色大片网站 | 日本免费色视频 | 成人午夜视频一区二区播放 | 日日操天天操 | 亚洲拍拍 | sm一区二区三区 | 俄罗斯毛片 | 欧美一区二区在线视频观看 | 亚洲欧洲自拍偷拍 | 九七电影院97理论片 | 欧美激情国产精品 | 在线免费观看一级片 | 黑人操少妇| 国产欧美一区二区三区在线看蜜臀 | 日本黄色片在线播放 | 亚洲tv在线观看 | 偷偷在线观看免费高清av | 99re6在线观看 | 天天宗合网 | 一个综合色| 三级网站在线 | 日日日操| 精品国产黄 | 日本欧美国产 | 成人h视频 | 成了校长的性脔h文 | 久久久精品视频在线观看 | 91免费看片网站 | 日韩电影在线观看一区 | 色综合亚洲 | 精品国产成人亚洲午夜福利 | 国产精品午夜无码专区 | 亚洲精品日韩av | 91偷拍精品一区二区三区 | 国产香蕉一区二区三区 | 大牛影视剧免费播放在线 | 欧美91视频 | 久伊人| 99中文字幕在线观看 | 亚州男人天堂 | 99热这里只| 久久久不卡国产精品一区二区 | 色一五月 | 第色| 男生插女生网站 | 亚洲免费网站在线观看 | 亚洲 另类 春色 国产 | 久久免费小视频 | 日本丰满熟妇bbxbbxhd | 脱裤吧导航 | 一级片一级片 | 黄网站免费大全入口 | 自拍偷拍第五页 | 国产亚洲精品久久久久四川人 | 性视频久久 | 久久久久国色av免费观看性色 | 亚洲色图综合 | 国产偷啪 | a级网站在线观看 | 激情国产精品 | 色婷婷国产精品 | 日本老熟妇乱 | 97自拍网 | 黄网视频在线观看 | 国产成人av在线播放 | 亚洲精品福利网站 | 人操人视频 | 最近中文字幕第一页 | 中国在线观看视频高清免费 | 天天干,天天干 | 黄色二级视频 | 夜夜高潮夜夜爽国产伦精品 | 亚洲精品第二页 | 精品国产91乱码一区二区三区 | 成人免费看 | 中文字幕一区二区三 | xxxx18国产| 婷婷五月综合缴情在线视频 | 国产高潮失禁喷水爽到抽搐 | 影音先锋成人资源网 | 亚洲av乱码久久精品蜜桃 | 法国空姐在线观看视频 | √天堂资源地址在线官网 | 欧美成年人在线视频 | 日韩丰满少妇 | 日韩精品在线观看一区二区 | 免费不卡视频 |