当前位置: 首页 > news >正文

ACM知识点总结 -【搜索技术】

 本系列适用于有些基础的同学食用,因为我个人感觉那些大佬写的文章太深奥了,每个人有每个人的代码风格,还是自己写出来的代码自己看着舒服,所以我就开始写ACM知识点部分,后面会有习题及其讲解,基础的概念在本系列文章中不做过多赘述,希望大家能够理解。本系列会持续更新,希望大家多多关注。 

目录

1.1递归和排列

(1)用STL输出全排列

(2)用递归求全排列

1.2子集生成和组合问题

1.3 BFS 

1.4八数码问题与状态图搜索

 1.5 BFS与A*算法

1.6 双向广搜

1.7 DFS

1.8 IDA*


 

1.1递归和排列

由于性能问题,全排列采用4个数字

(1)用STL输出全排列

//用STL输出全排列
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(register int i=x;i<=y;i++)
int main(){int data[10]={1,5,6,8,7,9,3,2,4};sort(data,data+4);//前n个数的全排列,按照字典序 do{fo(i,0,3) cout<<data[i]<<" ";cout<<endl;}while(next_permutation(data,data+4));return 0;
} 

(2)用递归求全排列

#include<bits/stdc++.h>
using namespace std;
#define Swap(a,b) {int temp=a;a=b;b=temp;}
#define fo(i,a,b) for( int i=a;i<=b;i++)
int data[4]={4,2,1,3};
int num=0;void pri_a(){fo(i,0,3) cout<<data[i]<<" ";cout<<endl;
}
int Perm(int begin,int end){if(begin==end){pri_a();num++;}else{for(int i=begin;i<=end;i++){Swap(data[begin],data[i]);Perm(begin+1,end);Swap(data[begin],data[i]);	}}
}
int main(){clock_t be,en;be=clock();sort(data,data+4);Perm(0,3);en=clock();cout<<(double)(en-be)/1000<<endl;cout<<num;return 0;
} 

运行结果如下: 

 注:上述代码中添加了一个测试运行时间的函数

1.2子集生成和组合问题

如何求n个数的子集?

#include<bits/stdc++.h>
#define fo(i,a,b) for( int i=a;i<=b;i++)
using namespace std;
void p(int n){for(int i=0;i<(1<<n);i++){fo(j,0,n-1){if(i&(1<<j)){cout<<j<<" ";}}cout<<endl;}
} 
int main(){int n;cin>>n;p(n);return 0;
} 

如何打印n个数中任意m个数的组合?

#include<bits/stdc++.h>
#define fo(i,a,b) for( int i=a;i<=b;i++)
using namespace std;
void p(int n,int m){fo(i,0,(1<<n)-1){int num=0,kk=i;while(kk){kk=kk&(kk-1);num++;}if(num==m){fo(j,0,n-1){if(i&(1<<j)) cout<<j<<" ";}cout<<endl;}}
}
int main(){int n,m;cin>>n>>m;p(n,m);return 0;
} 

1.3 BFS 

以杭电oj的一个习题引入→题目传送门

#include<iostream>
#include<queue>
#define fo(i,a,b) for( int i=a;i<=b;i++)
using namespace std;
char room[23][23];
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int n,m,num;
#define check(x,y) (x<n && x>=0 && y>=0 && y<m)
struct node{int x,y;
};
void bfs(int bx,int by){num=1;queue<node>q;node stare;stare.x=bx;stare.y=by;q.push(stare);while(!q.empty()){stare=q.front();q.pop();fo(i,0,3){node temp;temp.x=stare.x+dir[i][0];temp.y=stare.y+dir[i][1];if(check(temp.x,temp.y) && room[temp.x][temp.y]=='.'){room[temp.x][temp.y]='#';num++;q.push(temp);}}}
}
int main(){int bx,by;while(cin>>m>>n){if(n==0 && m==0) break;fo(i,0,n-1){fo(j,0,m-1){cin>>room[i][j];if(room[i][j]=='@'){bx=i;by=j;}}}num=0;bfs(bx,by);cout<<num<<endl;}return 0;
} 

这道题属于经典的模版题,没有什么特殊的难点。

1.4八数码问题与状态图搜索

八数码问题解析

康托展开

题目传送门

#include<bits/stdc++.h>
#define fo(i,a,b) for( int i=a;i<b;i++)
using namespace std;
const int LEN=362880;
struct node{int state[9];int dis;
};
int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int visited[LEN]={0};
int state[9];
int goal[9];
long int factory[]={1,1,2,6,24,120,720,5040,40320,362880};//康托展开
bool Cantor(int str[],int n){long result = 0;fo(i,0,n){int counted=0;fo(j,i+1,n-1){if(str[i]>str[j]) ++counted;}result+=counted*factory[n-i-1];}if(!visited[result]){visited[result]=1;return 1;}else return 0;
} 
int bfs(){node head;memcpy(head.state,state,sizeof(head.state));//复制起点状态head.dis=0;queue<node>q;Cantor(head.state,9);q.push(head);while(!q.empty()){head=q.front();q.pop();int z;for(z=0;z<9;z++){//找元素为0的位置 if(head.state[z]==0) {break;}}//转换为二维 int x=z%3;int y=z/3;fo(i,0,4){int newx=x+dir[i][0];int newy=y+dir[i][1];int nz=newx+3*newy;//转换为一维 if(newx>=0 && newx<3 && newy>=0 && newy<3){node newnode;memcpy(&newnode,&head,sizeof(struct node));//复制新状态swap(newnode.state[z],newnode.state[nz]);newnode.dis++;if(memcmp(newnode.state,goal,sizeof(goal))==0){return newnode.dis;} if(Cantor(newnode.state,9)){q.push(newnode);}} }} return -1;
}
int main(){fo(i,0,9) cin>>state[i];fo(i,0,9) cin>>goal[i];int num=bfs();if(num!=-1) cout<<num<<endl;else cout<<"Impossible"<<endl;return 0;
} 

这道题与杭电oj上面的题有点不同

 1.5 BFS与A*算法

这里用两篇文章来简单介绍一下

BFS

A*算法

简单来说,A*算法就是“BFS+贪心”。

上述八数码问题可以用这一算法来实现,因为我还没写出来,所以先空着,后序再来补充。

代码

1.6 双向广搜

双向广搜简介

题目传送门

1.7 DFS

题目传送门

#include<iostream>
#include<algorithm>
#include<string>
#define fo(i,a,b) for(int i=a;i<b;i++)
using namespace std;
int n,tot=0;
int col[12]={0};
bool check(int c,int r){fo(i,0,r){if(col[i]==c || (abs(col[i]-c)==abs(i-r))){return false;}}return true;
} 
void dfs(int r){if(r==n) {tot++;return;}fo(c,0,n){if(check(c,r)){col[r]=c;dfs(r+1);}}
}
int main(){int ans[12]={0};fo(i,1,12){memset(col,0,sizeof(col));tot=0;n = i; dfs(0);ans[i-1]=tot; }while(cin>>n){if(n==0){return 0;}cout<<ans[n-1]<<endl; }return 0;
}

1.8 IDA*

题目传送门

#include<iostream>
#define fo(i,a,b) for( int i=a;i<b;i++)
using namespace std;
int val[1010];
int pos,n;
bool ida(int now,int depth){if(now>depth) return false;if(val[pos]<<(depth-now)<n) return false;if(val[pos]==n) return true;pos++;fo(i,0,pos){val[pos]=val[pos-1]+val[i];if(ida(now+1,depth)) return true;val[pos]=abs(val[pos-1]-val[i]);if(ida(now+1,depth)) return true;}pos--;return false;
}
int main(){while(cin>>n&&n){int depth;for(depth=0;;depth++){val[pos=0]=1;if(ida(0,depth)) break;}cout<<depth<<endl;}return 0;
}

文章持续更新中,如有不足之处欢迎留言

相关文章:

  • 【机器学习】欠拟合、过拟合和正则化
  • 高性能图表库SciChart WPF v8.8全新发布——提升渐变颜色映射高度
  • 力扣-长度最小的子数组
  • Linux操作系统:fork+exec进程创建
  • 如果教材这样讲--碳膜电阻、金属氧化膜电阻、金属膜电阻、保险丝电阻、绕线电阻的区别和用途
  • Docker 与微服务架构:从单体应用到容器化微服务的迁移实践
  • 微软全新开源的Agentic Web网络项目:NLWeb,到底是什么 ?
  • 2024-2025年AI领域重大事件深度解析:技术革命、产业重构与未来挑战
  • 机器学习与深度学习算法:从决策树到 GAN 的原理与 PyTorch 实现
  • 升级node@22后运行npm install报错 distutils not found
  • leetcode 83和84 Remove Duplicates from Sorted List 和leetcode 1836
  • 微服务的应用案例
  • JMeter-Websocket接口自动化
  • C++23中std::span和std::basic_string_view可平凡复制提案解析
  • SpringBoot的前世今生
  • 学习STC51单片机11(芯片为STC89C52RC)
  • 使用VLOOKUP查询两个表格,使用数字格式进行查询,如果返回NA错误,则使用文本格式进行查询
  • 实战:Dify智能体+Java=自动化运营工具!
  • 1 研发规划
  • java基础(方法)
  • 班级网站怎么做/seo教程自学入门教材
  • 网站切片 做程序/免费站推广网站2022
  • 如何做网站的教程视频/收录入口在线提交
  • 东营可以做网站的公司在哪/线上拓客渠道有哪些
  • 政府门户网站建设的现状/爱站网关键词挖掘工具站长工具
  • 做地方行业门户网站需要什么资格/网盘搜索引擎入口