文章目录
9.1 宽度优先搜索(广度优先搜索BFS)
由于其不断向外扩展的特性,常用于搜索最优值的问题。
需要用到队列queue。
例题9.1 Catch That Cow
好久没有写BFS题目了,还是熟悉的配方熟悉的味道。
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 100001;
struct node{
int pos;
int time;
}S;
int tpos;
bool used[MAXN];
queue<node> q;
node MoveTo(node u, int i);
int bfs();
int main(){
scanf("%d%d", &S.pos, &tpos);
S.time = 0;
used[S.pos] = true;
q.push(S);
printf("%d\n", bfs());
return 0;
}
int bfs(){
node u, v;
while(!q.empty()){
u = q.front();
q.pop();
for(int i=0; i<3; i++){
v = MoveTo(u, i);
if(v.pos == tpos){
return v.time;
}
q.push(v);
}
}
}
node MoveTo(node u, int i){
node v;
v.time = u.time + 1;
if(i == 0) v.pos = u.pos + 1;
else if(i == 1) v.pos = u.pos - 1;
else if(i == 2) v.pos = 2 * u.pos;
return v;
}
例题9.2 Find The Multiple
#include <iostream>
#include <queue>
using namespace std;
queue<long long> q;
int t;
long long bfs(){
long long u, v;
while(!q.empty()){
u = q.front();
q.pop();
if(u % t == 0){
return u;
}
q.push(u * 10);
q.push(u * 10 + 1);
}
}
int main(){
while(scanf("%d", &t) != EOF){
while(!q.empty()){
q.pop();
}
q.push(1);
printf("%lld\n", bfs());
}
return 0;
}
习题9.1 玛雅人的密码
#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct node{
string num;
int step;
}S;
int len;
queue<node> q;
int bfs();
string Swap(string u, int i, int j);
int main(){
while(cin >> len >> S.num){
while(!q.empty()){
q.pop();
}
S.step = 0;
q.push(S);
printf("%d\n", bfs());
}
return 0;
}
int bfs(){
node u, v;
while(!q.empty()){
u = q.front();
q.pop();
if(u.num.find("2012") != string::npos){
return u.step;
}
for(int i=0; i<len-1; i++){
v.num = Swap(u.num, i, i+1);
v.step = u.step + 1;
q.push(v);
}
}
return -1;
}
string Swap(string s, int i, int j){
char c = s[i];
s[i] = s[j];
s[j] = c;
return s;
}
9.2 深度优先搜索(BFS)
常常是为了知道问题是否有解,而一般不使用深度优先搜索求解最优解问题。
需要用到递归。
例题9.3 A Knight’s Journey
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 30;
int p, q;
bool visited[MAXN][MAXN];
int direction[8][2] = {
{-1, -2}, {1, -2}, {-2, -1}, {2, -1}, {-2, 1}, {2, 1}, {-1, 2}, {1, 2}
};
bool dfs(int x, int y, int step, string ans){
if(p * q == step){
cout << ans << endl << endl;
return true;
}
for(int i=0; i<8; i++){
int nx = x + direction[i][0];
int ny = y + direction[i][1];
char col = ny + 'A';
char row = nx + '1';
if(nx<0 || nx>=p || ny<0 || ny>=q || visited[nx][ny]){
continue;
}
visited[nx][ny] = true;
if(dfs(nx, ny, step+1, ans + col + row)){
return true;
}
visited[nx][ny] = false;
}
return false;
}
int main(){
int n;
scanf("%d", &n);
int caseNumber = 0;
while(n--){
scanf("%d%d", &p, &q);
memset(visited, false, sizeof(visited));
cout << "Scenario #" << ++caseNumber << ":" << endl;
visited[0][0] = true;
if(!dfs(0, 0, 1, "A1")){
cout << "impossible" << endl << endl;
}
}
return 0;
}
例题9.4 Square
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 25;
int sticks[MAXN];
bool visit[MAXN];
int m, side;
bool dfs(int sum, int number, int position){
if(number == 3){
return true;
}
int sample = 0;
for(int i=position; i<m; i++){
if(visit[i] || sum + sticks[i] > side || sticks[i] == sample){
continue;
}
visit[i] = true;
if(sum + sticks[i] == side){
if(dfs(0, number + 1, 0)){
return true;
}else{
sample = sticks[i];
}
} else{
if(dfs(sum + sticks[i], number, i+1)){
return true;
}else{
sample = sticks[i];
}
}
visit[i] = false;
}
return false;
}
int main(){
int n;
scanf("%d", &n);
while(n--){
int length = 0;
scanf("%d", &m);
for(int i=0; i<m; i++){
scanf("%d", &sticks[i]);
length += sticks[i];
}
memset(visit, false, sizeof(visit));
if(length % 4 != 0){
printf("no\n");
continue;
}
side = length / 4;
sort(sticks, sticks + m, greater<int>());
if(sticks[0] > side){
printf("no\n");
continue;
}
if(dfs(0, 0, 0)){
printf("yes\n");
} else{
printf("no\n");
}
}
return 0;
}
习题9.2 神奇的口袋
#include <iostream>
using namespace std;
const int MAXN = 20;
int a[MAXN];
int cnt, n, sum;
void dfs(int k){
if(k == n){
if(sum == 40){
cnt++;
}
return;
}
if(sum + a[k] <= 40){
sum += a[k];
dfs(k + 1);
sum -= a[k];
}
dfs(k + 1);
}
int main(){
scanf("%d", &n);
for(int i=0; i<n; i++){
scanf("%d", &a[i]);
}
dfs(0);
printf("%d\n", cnt);
return 0;
}
习题9.3 八皇后
提交网址 经典深搜题。
#include <iostream>
using namespace std;
int answer[92][8];
int tmp[8];
int cnt = 0;
bool canplace(int k, int m){
for(int i=0; i<k; i++){
if(tmp[i] == m || abs(tmp[i] - m) == k - i){
return false;
}
}
return true;
}
void dfs(int k){
if(k == 8){
for(int i=0; i<8; i++){
answer[cnt][i] = tmp[i];
}
cnt++;
return;
}
for(int i=1; i<=8; i++){
if(canplace(k, i)){
tmp[k] = i;
dfs(k + 1);
}
}
}
int main(){
dfs(0);
int n;
while(scanf("%d", &n) != EOF){
for(int i=0; i<8; i++){
printf("%d", answer[n-1][i]);
}
printf("\n");
}
return 0;
}