题目均来自kuangbin专题
搜索题就是把每种情况都回去遍历一遍从中取得结果,深搜主要考虑边界问题和终止情况,
有回溯的话也要考虑,宽搜主要问题是不能走重复的路,因此每个点都是第一次且只遍历一次,可以解决一些最小/或最短问题。
1
棋盘挑战
深搜
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=20;
char g[N][N];
bool col[N],row[N];
int n,k;
int ans;
void dfs(int u,int s){
if(s==k){
ans++;
return;
}
if(u>=n) return;
for(int i=0;i<n;i++){
if(!col[i] and g[u][i]=='#'){
col[i]=1;
// g[u][i]='#';
dfs(u+1,s+1);
col[i]=0;
// g[u][i]='.';
}
}
dfs(u+1,s);
}
void solve(){
while(cin>>n>>k and n!=-1 and k!=-1){
ans=0;
for(int i=0;i<n;i++) cin>>g[i];
memset(col,0,sizeof col);
memset(row,0,sizeof row);
dfs(0,0);
cout<<ans<<endl;
}
}
int main(){
solve();
return 0;
}
2
地牢
三维宽搜
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
int l,r,c2,sx,sy,sz,ex,ey,ez;
struct pos{
int x,y,z;
};
const int N=35;
char g[N][N][N];
int d[N][N][N];
int dx[6]={0,0,0,0,1,-1},dy[6]={1,0,-1,0,0,0},dz[6]={0,1,0,-1,0,0};
int bfs(int a,int b,int c,int a1,int b1,int c1){
memset(d,-1,sizeof d);
d[a][b][c]=0;
queue<pos> q;
q.push({a,b,c});
while(q.size()){
pos t=q.front();
q.pop();
for(int i=0;i<6;i++){
int tx=t.x+dx[i],ty=t.y+dy[i],tz=t.z+dz[i];
if(tx>=0 && tx<l && ty>=0 && ty<r && tz>=0 && tz<c2 && d[tx][ty][tz]==-1 && g[tx][ty][tz]!='#' ){
d[tx][ty][tz]=d[t.x][t.y][t.z]+1;
q.push({tx,ty,tz});
}
}
}
return d[a1][b1][c1];
}
int main() {
while(cin>>l>>r>>c2&&l!=0&&r!=0&&c2!=0)
{
for(int i = 0;i < l; i++){
getchar();
for(int j = 0;j < r;j++){
for(int k = 0;k < c2;k++){
cin >> g[i][j][k];
if(g[i][j][k] == 'S')
{
sx=i;
sy=j;
sz=k;
}
if(g[i][j][k]=='E')
{
ex=i;
ey=j;
ez=k;
}
}
getchar();
}
}
int b=bfs(sx,sy,sz,ex,ey,ez);
if(b==-1) cout<<"Trapped!"<<endl;
else cout<<"Escaped in "<<b<<" minute(s)."<<endl;
}
return 0;
}
3.catch the cow
一维宽搜
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int N=1e5+10;
int d[1000010];
int n,k;
int dx[3]={-1,1,2};
int bfs(){
memset(d,-1,sizeof d);
d[n]=0;
queue<int>q;
q.push(n);
while(q.size()){
int t=q.front();
if(t==k) break;
q.pop();
for(int i=0;i<3;i++){
int tx;
if(dx[i]==2) tx=t*2;
else tx=t+dx[i];
if(tx>=0 and d[tx]==-1 and tx<=100000){//这里必须要特判,不然会t
d[tx]=d[t]+1;
q.push(tx);
}
}
}
return d[k];
}
void solve(){
cin>>n>>k;
if(n>k) cout<<n-k<<endl;
else{
int dis=bfs();
cout<<dis<<endl;
}
}
int main(){
solve();
return 0;
}
4.Fliptile
二进制枚举;
爆搜需要2nm的复杂度,二进制枚举第一行只需要2m;
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
const int N=20;
int g[N][N],RES[N][N],tem[N][N];//tem数组用于记录反转标记;
int ans=0x3f3f3f3f;
int dx[5]={0,0,1,-1,0},dy[5]={0,1,0,0,-1};
void turn(int x,int y){
tem[x][y]=1;
for(int i=0;i<5;i++){
int tx=x+dx[i],ty=y+dy[i];
if(tx>=0 and tx<n and ty>=0 and ty<m)
g[tx][ty]^=1;
}
}
void solve(){
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i][j];
for(int k=0;k<1<<m;k++){
memset(tem,0,sizeof tem);
int backup[N][N];
memcpy(backup,g,sizeof g);
int res=0;
for(int i=0;i<m;i++){
if(k>>i&1) turn(0,i),res++;
}
for(int i=0;i<n-1;i++){
for(int j=0;j<m;j++){
if(g[i][j]==1) turn(i+1,j),res++;
}
}
int check=1;
for(int i=0;i<m;i++){
if(g[n-1][i]==1) {
check=0;
break;
}
}
if(check) {
if(ans>res){
ans=res;
memcpy(RES,tem,sizeof tem);
}
}
memcpy(g,backup,sizeof g);
}
if(ans!=0x3f3f3f3f) {
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cout<<RES[i][j]<<' ';
cout<<endl;
}
}else cout<<"IMPOSSIBLE"<<endl;
}
int main(){
solve();
return 0;
}
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll n,m;
int check;
void dfs(int x,ll y){
if(x>19 or check) return ;//ll最多19位数字
if(y%n==0 and y>=n){
check=1;
m=y;
return;
}
dfs(x+1,y*10);
dfs(x+1,y*10+1);
}
void solve(){
while(cin>>n,n){
check=0;
dfs(1,1);
cout<<m<<endl;
}
}
int main(){
solve();
return 0;
}
6.Prime Path
宽搜+线性筛;
#include <iostream>
#include <algorithm>
#include <map>
#include <queue>
using namespace std;
const int N=100000;
int a,b;
map<int,int> m;//存储数字是否出现;
map<int,int> pri;//存储素数;
struct node{
int data,step;
};
int turn(int n,int x,int p){//改变数字函数;
if(p==1) n=n/10*10+x;
else if(p==2) n=n/100*100+x*10+n%10;
else if(p==3) n=n/1000*1000+x*100+n%100;
else if(p==4) n=n%1000+x*1000;
return n;
}
int prime[N];
bool st[N];
void isprime(){//线性筛;
int cnt=0;
for(int i=2;i<=10000;i++){
if(!st[i]) prime[cnt++]=i;
for(int j=0;prime[j]<=10000/i;j++){
st[prime[j]*i]=true;
if(i%prime[j]==0) break;
}
}
for(int i=0;i<=cnt;i++){
pri[prime[i]]++;
}
}
void bfs(){
node start={a,0};
queue<node> q;
node next;
q.push(start);
while(q.size()){
node now=q.front();
if(now.data==b) {
cout<<now.step<<endl;
break;
}
q.pop();
for(int i=0;i<=9;i++){
for(int j=1;j<=4;j++){
next.data=turn(now.data,i,j);
if(next.data>=1000 and next.data<=9999 and m[next.data]==0 and pri[next.data]==1){
m[next.data]++;
next.step=now.step+1;
q.push(next);
}
}
}
}
}
void solve(){
int t;
cin>>t;
isprime();
while(t--){
m.clear();
cin>>a>>b;
bfs();
}
}
int main(){
solve();
}
7.Shuffle’m Up
递归+模拟;
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
map<string,int> m;//用于存储已经拼接过的字符串;
int ans;
int n;
void dfs(string a,string b,string target){
string c="";
for(int i=0;i<2*n;i++){//拼接过程;
if(i&1) c+=a[i/2];
else c+=b[i/2];
}
ans++;
if(c==target){
return ;
}
if(m[c]==1) {//遇到已经拼接过的就return,不然会死循环;
ans=-1;
return ;
}
m[c]++;
a=c.substr(0,n),b=c.substr(n);//拆分过程;
dfs(a,b,target);
}
void solve(){
int t;
cin>>t;
string a,b,target;
for(int i=1;i<=t;i++){
cin>>n>>a>>b>>target;
ans=0;
dfs(a,b,target);
cout<<i<<' '<<ans<<endl;
}
}
int main(){
solve();
return 0;
}
8.Pots
宽搜;
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
int a,b,c;
const int N=110;
int vis[N][N];
struct node
{
int step;
int x,y;
string op;
};
string opp[7]={"","FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
int check;
void bfs(){
memset(vis,0,sizeof vis);
vis[0][0]=1;
queue<node> q;
q.push({0,0,0,""});
node next;
while(q.size()){
node now=q.front();
if(now.x==c or now.y==c){
cout<<now.step<<endl;
check=1;
for(int i=0;i<now.op.size();i++){
cout<<opp[now.op[i]-'0']<<endl;
}
break;
}
q.pop();
if(now.x<a){
if(!vis[a][now.y]){//倒满1号;
vis[a][now.y]=1;
next.x=a;
next.y=now.y;
next.step=now.step+1;
next.op=now.op+"1";
q.push(next);
}
}if(now.y<b){//倒满2号;
if(!vis[now.x][b]){
vis[now.x][b]=1;
next.y=b;
next.x=now.x;
next.step=now.step+1;
next.op=now.op+"2";
q.push(next);
}
} if(now.x){//倒光1号;
next.x=0;
next.y=now.y;
next.step=now.step+1;
next.op=now.op+"3";
if(!vis[0][next.y]){
vis[0][next.y]=1;
q.push(next);
}
} if(now.y){//倒光2号;
next.y=0;
next.x=now.x;
next.step=now.step+1;
next.op=now.op+"4";
if(!vis[next.x][0]){
vis[next.x][0]=1;
q.push(next);
}
} if(now.x and now.y<b){
int t=b-now.y;
if(now.x-t>0){//1号倒不光;
next.x=now.x-t;
next.y=b;
}else{//倒光;
next.x=0;
next.y=now.y+now.x;
}
next.step=now.step+1;
next.op=now.op+"5";
if(!vis[next.x][next.y]){
vis[next.x][next.y]=1;
q.push(next);
}
} if(now.y and now.x<a){
int t=a-now.x;
if(now.y-t>0){//2号倒不光;
next.y=now.y-t;
next.x=a;
}else {//倒光;
next.y=0;
next.x=now.x+now.y;
}
next.step=now.step+1;
next.op=now.op+"6";
if(!vis[next.x][next.y]){
vis[next.x][next.y]=1;
q.push(next);
}
}
}
}
void solve(){
cin>>a>>b>>c;
bfs();
if(!check) cout<<"impossible"<<endl;
}
int main(){
solve();
return 0;
}
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int N=10;
int g[N][N];
int vis[N][N];
typedef pair<int,int> pii;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
struct node{
int x,y;
vector<pii> op;
};
void bfs(){
queue<node> q;
node now;
now.x=0,now.y=0,now.op.push_back({0,0});
q.push(now);
vis[0][0]=1;
node next;
while(q.size()){
now=q.front();
if(now.x==4 and now.y==4){
for(int i=0;i<now.op.size();i++){
cout<<"("<<now.op[i].first<<", "<<now.op[i].second<<")"<<endl;
}
break;
}
q.pop();
for(int i=0;i<4;i++){
next.x=now.x+dx[i],next.y=now.y+dy[i];
next.op=now.op;
next.op.push_back({next.x,next.y});
if(next.x>=0 and next.x<5 and next.y>=0 and next.y<5 and !vis[next.x][next.y] and g[next.x][next.y]!=1){
vis[next.x][next.y]=1;
q.push(next);
}
}
}
}
void solve(){
for(int i=0;i<5;i++){
for(int j=0;j<5;j++)
cin>>g[i][j];
}
bfs();
}
int main(){
solve();
return 0;
}
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1010;
char g[N][N];
int vis[N][N];
int d[N][N];
#define x first
#define y second
int r, c;
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
typedef pair<int, int> pii;
void bfs_fire() {
queue<pii> q;
memset(vis, -1, sizeof vis);
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
if (g[i][j] == 'F') {
q.push({i, j});
vis[i][j] = 0;
}
}
}
while (q.size()) {
pii now = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int tx = now.x + dx[i], ty = now.y + dy[i];
if (tx >= 1 and tx <= r and ty >= 1 and ty <= c and vis[tx][ty] == -1 and g[tx][ty] != '#') {
vis[tx][ty] = vis[now.x][now.y] + 1;
q.push({tx, ty});
}
}
}
}
void bfs_j(int jx, int jy) {
memset(d, -1, sizeof d);
int check = 0;
d[jx][jy] = 0;
queue<pii> q;
q.push({jx, jy});
while (q.size()) {
pii now = q.front();
q.pop();
if (now.x == 1 or now.x == r or now.y == 1 or now.y == c) {
check = 1;
cout << d[now.x][now.y] + 1 << endl;
break;
}
for (int i = 0; i < 4; i++) {
int tx = now.x + dx[i], ty = now.y + dy[i];
if (tx >= 1 and tx <= r and ty >= 1 and ty <= c and d[tx][ty] == -1 and g[tx][ty] != '#') {
if (vis[tx][ty] != -1 and d[now.x][now.y] + 1 >= vis[tx][ty]) continue;
d[tx][ty] = d[now.x][now.y] + 1;
q.push({tx, ty});
}
}
}
if (!check) cout << "IMPOSSIBLE" << endl;
}
void solve() {
cin >> r >> c;
int jx, jy;
for (int i = 1; i <= r; i++) {
for (int j = 1; j <= c; j++) {
cin >> g[i][j];
if (g[i][j] == 'J') jx = i, jy = j;
}
}
bfs_fire();
bfs_j(jx, jy);
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N=110;
char g[N][N];
struct node
{
int x,y;
};
int dx[8]={1,0,-1,0,1,1,-1,-1},dy[8]={0,1,0,-1,1,-1,1,-1};
int vis[N][N];
int n,m;
int bfs(){
int res=0;
int cnt=0;
memset(vis,0,sizeof vis);
queue<node> q;
node now; node next;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(g[i][j]=='@' and !vis[i][j]) {
cnt=1;
q.push({i,j});
vis[i][j]=1;
while(q.size()){
now=q.front();
q.pop();
for(int i=0;i<8;i++){
next.x=now.x+dx[i],next.y=now.y+dy[i];
if(next.x>=1 and next.x<=n and next.y>=1 and next.y<=m and !vis[next.x][next.y] and g[next.x][next.y]=='@'){
q.push(next);
vis[next.x][next.y]=1;
}
}
}
}
if(cnt>=1) res++,cnt=0;
}
}
return res;
}
void solve(){
while(cin>>n>>m,n and m){
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cin>>g[i][j];
}
int res=bfs();
cout<<res<<endl;
}
}
int main(){
solve();
return 0;
}
非常可乐
倒水问题bfs
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
int a, b, c;
const int N = 110;
int vis[N][N][N];
struct node {
int x, y, z;
int step;
string op;
};
void bfs() {
memset(vis, 0, sizeof vis);
vis[a][0][0] = 1;
queue<node> q;
int check = 0;
node next;
q.push({a, 0, 0, 0, ""});
int sum = a;
sum /= 2;
while (q.size()) {
node now = q.front();
q.pop();
if ((now.x == sum and now.y == sum) or (now.x == sum and now.z == sum) or (now.y == sum and now.z == sum) ) {
check = 1;
cout << now.step << endl;
// cout<<now.op<<endl;
// cout<<now.x<<' '<<now.y<<' '<<now.z<<endl;
break;
}
if (now.x and now.y < b) { //x->y;
int t = b - now.y;
if (now.x <= t) {
next.x = 0;
next.y = now.x + now.y;
} else {
next.x = now.x - t;
next.y = now.y + t;
}
next.z = now.z;
next.step = now.step + 1;
if (!vis[next.x][next.x][next.z]) {
vis[next.x][next.x][next.z] = 1;
next.op = now.op + " x->y";
q.push(next);
}
}
if (now.x and now.z < c) { //x->z;
int t = c - now.z;
if (now.x <= t) {
next.x = 0;
next.z = now.x + now.z;
} else {
next.x = now.x - t;
next.z = now.z + t;
}
next.y = now.y;
next.step = now.step + 1;
if (!vis[next.x][next.x][next.z]) {
vis[next.x][next.x][next.z] = 1;
next.op = now.op + " x->z";
q.push(next);
}
}
if (now.y and now.x < a) { //y->x;
int t = a - now.x;
if (now.y <= t) {
next.y = 0;
next.x = now.y + now.x;
} else {
next.y = now.y - t;
next.x = now.x + t;
}
next.z = now.z;
next.step = now.step + 1;
if (!vis[next.x][next.x][next.z]) {
vis[next.x][next.x][next.z] = 1;
next.op = now.op + " y->x";
q.push(next);
}
}
if (now.y and now.z < c) { //y->z;
int t = c - now.z;
if (now.y <= t) {
next.y = 0;
next.z = now.z + now.y;
} else {
next.y = now.y - t;
next.z = now.z + t;
}
next.x = now.x;
next.step = now.step + 1;
if (!vis[next.x][next.x][next.z]) {
vis[next.x][next.x][next.z] = 1;
next.op = now.op + " y->z";
q.push(next);
}
}
if (now.z and now.x < a) { //z->x;
int t = a - now.x;
if (now.z <= t) {
next.z = 0;
next.x = now.x + now.z;
} else {
next.z = now.z - t;
next.x = now.x + t;
}
next.y = now.y;
next.step = now.step + 1;
if (!vis[next.x][next.x][next.z]) {
vis[next.x][next.x][next.z] = 1;
next.op = now.op + " z->x";
q.push(next);
}
}
if (now.z and now.y < b) { //z->y;
int t = b - now.y;
if (now.z <= t) {
next.z = 0;
next.y = now.z + now.y;
} else {
next.z = now.z - t;
next.y = now.y + t;
}
next.x = now.x;
next.step = now.step + 1;
if (!vis[next.x][next.x][next.z]) {
vis[next.x][next.x][next.z] = 1;
next.op = now.op + " z->y";
q.push(next);
}
}
}
if (!check) cout << "NO" << endl;
}
void solve() {
while (cin >> a >> b >> c, a and b and c) {
if (a & 1) cout << "NO" << endl;
else
bfs();
}
}
int main() {
solve();
return 0;
}
Find a way
两次bfs求和
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int N = 250;
int d1[N][N], d2[N][N];
char g[N][N];
int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
#define x first
#define y second
int n, m;
int ans = 0x7fffffff;
typedef pair<int, int> pii;
void bfs(int x, int y, int k) {
if (k == 1) {
memset(d1, -1, sizeof d1);
d1[x][y] = 0;
queue<pii> q;
q.push({x, y});
while (q.size()) {
pii now = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int tx = now.x + dx[i], ty = now.y + dy[i];
if (tx >= 1 and tx <= n and ty >= 1 and ty <= m and g[tx][ty] != '#' and d1[tx][ty] == -1) {
d1[tx][ty] = d1[now.x][now.y] + 11;
q.push({tx, ty});
}
}
}
} else {
memset(d2, -1, sizeof d2);
d2[x][y] = 0;
queue<pii> q;
q.push({x, y});
while (q.size()) {
pii now = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int tx = now.x + dx[i], ty = now.y + dy[i];
if (tx >= 1 and tx <= n and ty >= 1 and ty <= m and g[tx][ty] != '#' and d2[tx][ty] == -1) {
d2[tx][ty] = d2[now.x][now.y] + 11;
q.push({tx, ty});
}
}
}
}
}
void get_res() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (g[i][j] == '@' and d1[i][j] != -1 and d2[i][j] != -1) {
ans = min(ans, d1[i][j] + d2[i][j]);
}
}
}
}
void solve() {
int x1, y1, x2, y2;
while (cin >> n >> m) {
ans = 0x7fffffff;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
char& c = g[i][j];
cin >> c;
if (c == 'Y') x1 = i, y1 = j;
if (c == 'M') x2 = i, y2 = j;
}
}
bfs(x1, y1, 1);
bfs(x2, y2, 2);
get_res();
cout << ans << endl;
}
}
int main() {
solve();
return 0;
}
附加:2n皇后
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
int n;
const int N = 20;
bool col_w[N], dg_w[N], udg_w[N];
bool col_b[N], dg_b[N], udg_b[N];
int ans;
int g[N][N];
int g_n[N][N];
void dfs(int u, int c) {
if (u == n + 1) {
puts("");
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cout << g_n[i][j] << ' ';
}
cout << endl;
}
u = 1, c++;
}
if (c == 1) {
for (int i = 1; i <= n; i++) {
if (!col_w[i] and !dg_w[u + i] and !udg_w[u - i + n] and g[u][i]) {
col_w[i] = dg_w[u + i] = udg_w[u - i + n] = 1;
g_n[u][i] = c + 1;
g[u][i] = 0;
dfs(u + 1, c);
col_w[i] = dg_w[u + i] = udg_w[u - i + n] = 0;
g_n[u][i] = 0;
g[u][i] = 1;
}
}
} else if (c == 2) {
for (int i = 1; i <= n; i++) {
if (!col_b[i] and !dg_b[u + i] and !udg_b[u - i + n] and g[u][i]) {
col_b[i] = dg_b[u + i] = udg_b[u - i + n] = 1;
g_n[u][i] = c + 1;
g[u][i] = 0;
dfs(u + 1, c);
col_b[i] = dg_b[u + i] = udg_b[u - i + n] = 0;
g_n[u][i] = 0;
g[u][i] = 1;
}
}
} else {
ans++;
return;
}
}
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++)
cin >> g[i][j];
}
dfs(1, 1);
printf("%d\n", ans);
}
int main() {
solve();
}
//简单搜索专题结束啦,之后会开进阶搜索专题//