2018-7-11 ACM 專項刷題 dfs + bfs
1. 遞迴:
先說一個遞迴的含義,就是在某個函式內部呼叫這個函式本身,或者說,呼叫一個與該函式完全相同的函式。
最簡單的一個遞迴的應用就是,輾轉相除法求最大公約數Gcd:
LL gcd(LL x, LL y) {
if(x % y == 0) return y;
else return gcd(y, x % y);
}
2. dfs(深度優先搜尋):
dfs 也有幾個很常見的應用,基礎思想也是遞迴,下面簡單說下常見的dfs應用:
(1)八皇后問題 & N皇后問題:
對應題目:HDU - 2553
八皇后問題,就是在8 * 8的棋盤上擺放八個皇后,要求這八個皇后,不同行,不同列,不同對角線, 問多少種擺法。
程式碼如下:
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>usingnamespace std;#define N 8//八皇后int ans;int col[10];//col[i]表示, 第i行的皇后放在第col[i]列void dfs(int k){if(k == N) ans++;else{for(int i =0; i < N; i++){bool flg =1;
col[k]= i;for(int j =0; j < k; j++){//判斷第k行的皇后與第j行的皇后是否在同一列, 是否在同一對角線if(col[k]== col[j]|| k - col[k]== j - col[j]|| k + col[k]== j + col[j]){
flg =0;//同一主對角線上的元素的(行 - 列)是一個常數, 同一副對角線上的元素的(行 + 列)是一個常數break;}}if(flg) dfs(k +1);}}}int main(){
dfs(0);
printf("%d\n", ans );}
接下來是N皇后,開一個全域性的N即可,傳入一個N,為了防止超時,可以打表,程式碼如下:
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>usingnamespace std;int col[13];int N;/*void dfs(int k) {
if(k == N) ans++;
else {
for(int i = 0; i < N; i++) {
bool flg = 1;
col[k] = i;
for(int j = 0; j < k; j++) {
if(col[k] == col[j] || k - col[k] == j - col[j] || k + col[k] == j + col[j]) {
flg = 0;
break;
}
}
if(flg) dfs(k + 1);
}
}
}*/int ans[11]={-1,1,0,0,2,10,4,40,92,352,724};int main(){while(~scanf("%d",&N)&& N){//ans = 0;//dfs(0);
printf("%d\n", ans[N]);}}
所謂打表,就是將 dfs 跑出的 1 ~ 10 皇后的結果存進ans陣列,在輸出ans[N]即可。
(2)全排列問題:
對應題目:HDU - 1716
先說下 1 ~ N 的全排列(字典序升序),程式碼如下:
#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<algorithm>usingnamespace std;int n;bool vis[10];int ans[10];voidDfs(int x){if(x == n +1){for(int i =1; i <= n; i++) printf("%d ", ans[i]);
printf("\n");}for(int i =1; i <= n; i++){if(!vis[i]){
vis[i]=1;
ans[x]= i;Dfs(x +1);
vis[i]=0;}}}int main(){
scanf("%d",&n);Dfs(1);return0;}
下面仿照上面的思路,寫一下傳進任意四個數,所能形成的四位數的全排列(以字典序升序),程式碼如下:
#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<cmath>#include<iostream>#include<algorithm>usingnamespace std;constint maxx =1e5+7;bool vis[10];int ans[10];int t[10];int n;bool chk[maxx];int res[maxx];int p;voidDfs(int x){if(x ==5){int tmp =0;for(int i =1; i <=4; i++){
tmp += ans[i]* pow(10,4- i);}if(!chk[tmp]&& tmp >=1000){
p++;
res[p]= tmp;
chk[tmp]=1;}}for(int i =1; i <=4; i++){if(!vis[i]){
vis[i]=1;
ans[x]= t[i];Dfs(x +1);
vis[i]=0;}}}int main(){bool flg =0;int cnt =-1;while(scanf("%d %d %d %d",&t[1],&t[2],&t[3],&t[4]) != EOF){if(t[1]==0&& t[2]==0&& t[3]==0&& t[4]==0)break;
memset(chk,0,sizeof(chk));
memset(vis,0,sizeof(vis));
memset(res,0,sizeof(res));
p =0;
sort(t +1, t +5);Dfs(1);for(int i =1; i <= p; i++) printf("%d\n", res[i]);}}
(3)連通及連通塊問題:
對應題目:HDU - 1312 、HDU - 1241 、Codeforces - 377A 、POJ - 2386
HDU - 1312 題解:
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>usingnamespace std;int n, m, ans;char str[25][25];int dx[5]={-1,0,1,0};int dy[5]={0,-1,0,1};void dfs(int x,int y){if(x <1|| x > n || y <1|| y > m)return;if(str[x][y]!='.')return;
ans++;
str[x][y]='#';for(int i =0; i <4; i++){int xx = x + dx[i];int yy = y + dy[i];
dfs(xx, yy);}}int main(){while(~scanf("%d %d",&m,&n)){if(n ==0&& m ==0)break;int x, y;
ans =0;for(int i =1; i <= n; i++){for(int j =1; j <= m; j++) scanf(" %c",&str[i][j]);}for(int i =1; i <= n; i++){for(int j =1; j <= m; j++){if(str[i][j]=='@') x = i, y = j;}}
str[x][y]='.';
dfs(x, y);
printf("%d\n", ans);}return0;}
HDU - 1241 題解:
#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>usingnamespace std;int n, m;char s[110][110];void dfs(int x,int y){if(x <1|| x > n || y <1|| y > m)return;if(s[x][y]=='*')return;
s[x][y]='*';for(int i =-1; i <=1; i++){for(int j =-1; j <=1; j++){if(i !=0|| j !=0) dfs(x + i, y + j);}}}int main(){while(~scanf("%d %d",&n,&m)&& n && m){int ans =0;for(int i =1; i <= n; i++)for(int j =1; j <= m; j++) scanf(" %c",&s[i][j]);for(int i =1; i <= n; i++){for(int j =1; j <= m; j++){if(s[i][j]=='@'){
ans++;
dfs(i, j);}}}
printf("%d\n", ans);}}
Codeforces - 377A 題解:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int h, w, t;
char str[550][550];
void dfs(int x, int y) {
if(x < 1 || x > h || y < 1 || y > w) return;
if(str[x][y] != '.') return;
str[x][y] = '!';
int num = 0;
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
if(!t) return;
if(fabs(i) != fabs(j)) {
dfs(x + i, y + j);
if(str[x + i][y + j] == '.') num++;
}
}
}
if(num == 0) {
str[x][y] = 'X';
t--;
}
}
int main() {
scanf("%d %d %d", &h, &w, &t);
for(int i = 1; i <= h; i++) {
for(int j = 1; j <= w; j++) scanf(" %c", &str[i][j]);
}
for(int i = 1; i <= h; i++) {
for(int j = 1; j <= w; j++) {
dfs(i, j);
}
}
for(int i = 1; i <= h; i++) {
for(int j = 1; j <= w; j++) {
if(str[i][j] == '!') str[i][j] = '.';
}
}
for(int i = 1; i <= h; i++) {
for(int j = 1; j <= w; j++) printf("%c", str[i][j]);
printf("\n");
}
return 0;
}
POJ - 2386 題解:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m;
char str[110][110];
void dfs(int x, int y) {
if(x < 1 || x > n || y < 1 || y > m) return;
if(str[x][y] == '.') return;
str[x][y] = '.';
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
if(i != 0 || j != 0) dfs(x + i, y + j);
}
}
}
int main() {
int p = 0;
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) scanf(" %c", &str[i][j]);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(str[i][j] == 'W') {
p++;
dfs(i, j);
}
}
}
printf("%d\n", p);
return 0;
}
(4)可轉化為深搜的其他應用:
對應題目:Codeforces - 96B
我不會轉化為dfs的模型,純暴力打表過的,我部落格寫過這題題解,詳見連結:
https://blog.csdn.net/ericgipsy/article/details/80164017
3. bfs(廣度優先搜尋):
(1)最短路問題:
bfs主要應用於求圖內某一點到另一點的最短路徑,模板程式碼如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx = 1e5 + 7;
const int Inf = 1 << 30;
char s[55][55];
int vis[55][55];
int dd[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
int n, m;
int ans, res;
struct PP {
int x, y, flg;
} p, q;
int Bfs(int x, int y) { //返回的是最短路徑經過的所有點的個數
memset(vis, 0, sizeof(vis));
queue <PP> qua;
p.x = x, p.y = y, p.flg = 1;
qua.push(p);
while(!qua.empty()) {
q = qua.front();
qua.pop();
if(q.x == n && q.y == m) return q.flg;
if(!vis[q.x][q.y]) {
vis[q.x][q.y] = 1;
for(int i = 0; i < 4; i++) {
int dx = q.x + dd[i][0];
int dy = q.y + dd[i][1];
if (dx >= 1 && dx <= n && dy >= 1 && dy <= m && s[dx][dy] != '#' && !vis[dx][dy]) {
PP tmp;
tmp.x = dx, tmp.y = dy, tmp.flg = q.flg + 1;
qua.push(tmp);
}
}
}
}
return -1;
}
void Init() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
}
int main() {
Init();
cout << Bfs(1, 1) << endl;
}
由於bfs對路徑是實時更新的,所以無法儲存路徑,可以藉助dfs或者vector儲存路徑。
對應題目:Atcoder Beginner Contest 088 - D
題解:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxx = 1e5 + 7; const int Inf = 1 << 30; char s[55][55]; int vis[55][55]; int dd[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; int n, m; int ans, res; struct PP { int x, y, flg; } p, q; int Bfs(int x, int y) { memset(vis, 0, sizeof(vis)); queue <PP> qua; p.x = x, p.y = y, p.flg = 1; qua.push(p); while(!qua.empty()) { q = qua.front(); qua.pop(); if(q.x == n && q.y == m) return q.flg; if(!vis[q.x][q.y]) { vis[q.x][q.y] = 1; for(int i = 0; i < 4; i++) { int dx = q.x + dd[i][0]; int dy = q.y + dd[i][1]; if (dx >= 1 && dx <= n && dy >= 1 && dy <= m && s[dx][dy] != '#' && !vis[dx][dy]) { PP tmp; tmp.x = dx, tmp.y = dy, tmp.flg = q.flg + 1; qua.push(tmp); } } } } return -1; } void Init() { scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1); } int main() { Init(); ans = n * m; for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) if(s[i][j] == '#') ans--; if(s[1][1] == '#' || s[n][m] == '#') res = -1; else res = Bfs(1, 1); if(res == -1) ans = -1; else ans -= res; cout << ans << endl; }
(2)可轉化為最短路的其他應用:
對應題目:POJ - 3278
POJ - 3278 題解:
#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<iostream>#include<algorithm>usingnamespace std;constint maxx =1e5+7;int N, K;bool vis[2* maxx];struct PP {int ans;int dp;} p, q;queue<PP> qua;intBfs(int n,int k){
p.ans =0, p.dp = n;
qua.push(p);while(!qua.empty()){
p = qua.front();
qua.pop();if(p.dp == k)return p.ans;if(p.dp < k &&!vis[p.dp *2]){
q.dp = p.dp *2;
q.ans = p.ans +1;
vis[q.dp]=1;
qua.push(q);}if(p.dp < k &&!vis[p.dp +1]){
q.dp = p.dp +1;
q.ans = p.ans +1;
vis[q.dp]=1;
qua.push(q);}if(p.dp -1>=0&&!vis[p.dp -1]){
q.dp = p.dp -1;
q.ans = p.ans +1;
vis[p.dp]=1;
qua.push(q);}}}int main(){
cin >> N >> K;if(N >= K) cout << N - K << endl;else cout <<Bfs(N, K)<< endl;return0;}
相關推薦
2018-7-11 ACM 專項刷題 dfs + bfs
1. 遞迴: 先說一個遞迴的含義,就是在某個函式內部呼叫這個函式本身,或者說,呼叫一個與該函式完全相同的函式。 最簡單的一個遞迴的應用就是,輾轉相除法求最大公約數Gcd: LL gcd(LL x, LL y) { if(x % y == 0) return y;
2018-7-19 ACM 專項刷題 最短路
最短路三種演算法的模板: 1. 弗洛伊德: #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <stri
2018-7-9 ACM 刷題日記
<Codeforces 977D>題意:給定一串序列,問能否讓序列形成一個順序,使得序列某一項是由它前一項乘2或者前一項整除3得來的,列印該順序。思路:一開始我的思路是這樣的,就是先找只能被3整除和只能被2整除的(即不能同時被3和2整除,即不能被6整除的數),然後
2018-7-18 ACM 刷題日記
<Codeforces - 1009B> 題意: 給定一個只由'0'、'1'、'2' 組成的串,只能將0 1互換,1 2互換,不能將0 2互換,求形成字典序最小的的串。 思路: 因為1既可以和0換,又可以和2換,所以1的位置是自由的,即1可以挪到任意位置,
python 2018.7.11
寫入 def 掌握 修改 line rename 重命名文件 讀寫 ada 1. r例 # 路徑有兩種:# 1. 相對路徑, 相對於你當前程序所在的文件夾.(必須掌握)# ../ 返回上一層目錄# 相對的是當前程序所在的文件夾# 2. 絕對路徑. 1.從
2018-7-11
roo editor chmod nbsp 時間 操作 Edito stat style 20.1 shell腳本介紹20.2 shell腳本結構和執行20.3 date命令用法20.4 shell腳本中的變量20.1 shell腳本介紹20.2 shell腳本結構和執行開
2018年暑假ACM個人訓練題9(動態規劃)解題報告
三角形 img 背包 使用 狀態 記憶化 logs ref wid A:m段最大字段和問題https://www.cnblogs.com/yinbiao/p/9314528.htmlB:m
11-1C/C++刷題
1、對於以下程式碼: char *p=new char[100] p在棧上 new出來的在堆上 動態分配在堆中,其他的記憶體分配都在棧上進行。 2、static char a[2]={‘1’,‘2’,‘3’};說法是都正確? 錯誤 陣列越界 3、在C語言的定義和呼叫中,函式的定義不
[刷題] dfs回溯 合集
題目: Permutations Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
2018/2/8 面試題刷題第三天
問1.知道的網頁製作會用到的圖片格式有哪些?答:png-8,png-24,jpeg,gif,svg。但是上面的那些都不是面試官想要的最後答案。面試官希望聽到是Webp,Apng。(是否有關注新技術,新鮮
2018/7/11學習筆記
JSON 在前後端傳輸中的使用: 在JS中 .stringify()將JS物件轉換為JSON字串。 .parse()將JSON字串轉換為JS物件。 在JAVA中 JSONObject(json string)將JSON字串轉換為JSON物件 JSON
手把手教你用C++ 寫ACM自動刷題神器(衝入HDU首頁)
少年,作為苦練ACM,通宵刷題的你 是不是想著有一天能夠榮登各大OJ榜首,俯瞰芸芸眾生,唔....要做到這件事情可是需要一定天賦的哦! 博主本身也搞過一段時間的acm,對刷題深有感觸,不信可以去看我部落格的acm題解(哈哈)。 不過,先給各位辛苦刷題的ACMer賠個不是,畢
7月18日刷題記錄 二分答案跳石頭遊戲Getting
通過數:1 明天就要暑假程式設計集訓啦~莫名開心 今天做出了一道 二分答案題(好艱辛鴨) 1049: B13-二分-跳石頭遊戲(二分答案) 時間限制: 5 Sec 記憶體限制: 256 MB提交: 30 解決: 12[提交]
2018-10-7 Atcoder 刷題日記
Atcoder Beginner 068 - C 題意: 有 n 個島嶼,k 條船,這 k 條船分別連線 ai 島嶼和 bi 島嶼,問能否只是用兩條船就從 島嶼1到達島嶼 n 思路: 這題我使用set處理的,當島嶼起點為1的時候,將其從島嶼1出發所能到達的所有島嶼 P
【LeetCode & 劍指offer刷題】查詢與排序題7:11旋轉陣列的最小數字(153. Find Minimum in Rotated Sorted Array)(系列)
【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...) 153. Find Minimum in Rotated Sorted Array Suppose an array sorted in ascending ord
2018-6-18 ACM 刷題日記
<Codeforces 990C>題意:給n個只由 '(' 和 ')' 組成的串,問從這些串中選出兩個串,使他們括號匹配,能夠成多少個匹配串,自身和自身組合匹配也算。以題中第二個樣例說明:輸入:2 ( ) ( )輸出:4解釋:輸入的兩個串 a,b 分別是 a: (
刷題總結——尋寶遊戲(bzoj3991 dfs序)
first 最短 更新數據 iostream begin 題解 長度 ras getchar 題目: Description 小B最近正在玩一個尋寶遊戲,這個遊戲的地圖中有N個村莊和N-1條道路,並且任何兩個村莊之間有且僅有一條路徑可達。遊戲開始時,玩家可以任意選擇一個
2017-10-7 清北刷題沖刺班a.m
同時 .cpp play 很多 註意 names 出現的次數 char fin 測試 A 消失的數字 文件名 輸入文件 輸出文件 時間限制 空間限制del.cpp/c/pas del.in del.out 1s 512MB題目描述現在,我的手上有 n 個數字,分別是 a
2017-10-7 清北刷題沖刺班p.m
-s 都沒有 iostream 路線 分數 dfs img 多次 單向 測試 A 同花順 文件名 輸入文件 輸出文件 時間限制 空間限制card.cpp/c/pas card.in card.out 1s 512MB題目描述所謂同花順,就是指一些撲克牌,它們花色相同,並
2017.11.11 ACM-ICPC2017亞洲區域賽(沈陽)重現賽 7/13 Rank10
數據 nbsp 需要 acm-icpc 進展 span 模擬 ron 能力 開場各自讀題 I題簽到..很快就過了.. 然後開了F..He寫了個暴力..Hong看了看找了個遞推式..餵給Huang拿JAVA寫了一下..很快就過了.. 然後發現K有很多人過..然後He就去開了K