BFS
Flood Fill
题单:
最短路
题单:
多源BFS
题单:
- 矩阵距离:初始队首元素不只有一个
最小步数模型
题单:
双端队列
题单:
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
const int N=510;
int r,c;
char g[N][N];
int dist[N][N];
int bfs(){
char move[]="\\/\\/";
int mx[]={-1,-1,1,1};
int my[]={-1,1,1,-1};
int ix[]={-1,-1,0,0};
int iy[]={-1,0,0,-1};
memset(dist,0x3f,sizeof dist);
dist[0][0]=0;
deque<PII> q;
q.push_front({0,0});
while(q.size()){
auto t=q.front();
q.pop_front();
if(t.x==r&&t.y==c) return dist[r][c];
for(int i=0;i<4;i++){
int ax=t.x+mx[i];
int ay=t.y+my[i];
int bx=t.x+ix[i];
int by=t.y+iy[i];
if(ax<0||ax>r||ay<0||ay>c) continue;
int w=g[bx][by]!=move[i];
int d=dist[t.x][t.y]+w;
if(d<dist[ax][ay]){
dist[ax][ay]=d;
if(!w) q.push_front({ax,ay});
else q.push_back({ax,ay});
}
}
}
return -1;
}
signed main(){
int t;
cin>>t;
while(t--){
cin>>r>>c;
//优化1
//if(r+c & 1 ){
// puts("NO SOLUTION");
// continue;
//}
for(int i=0;i<r;i++) cin>>g[i];
int res=bfs();
if(res==-1) puts("NO SOLUTION"); //(1)
else cout<<res<<endl;
}
return 0;
}
双向广搜
题单:
// 采用单向bfs搜索
// 数据一旦加强就过不了
# include<bits/stdc++.h>
using namespace std;
string A,B;
const int N=21;
vector<string> a(N),b(N);
int n;
int bfs(){
unordered_map<string,int> d;
queue<string> q;
q.push(A);
while(q.size()){
string t = q.front();
q.pop();
if(t==B) return d[t];
for(int i = 0; i < t.size(); i++){
for(int j=0; j < n; j ++){
if(t.substr(i,a[j].size()) == a[j]){
string sub=t.substr(0,i)+b[j]+t.substr(i+a[j].size());
if(!d.count(sub)){
d[sub]=d[t]+1;
q.push(sub);
}
}
}
}
}
return -1;
}
signed main(){
cin>>A>>B;
while(cin>>a[n]>>b[n++]);
int t=bfs();
if(t!=-1) cout<<t<<endl;
else puts("NO ANSWER!");
return 0;
}
// 采用双向bfs搜索
// y总版
# include<bits/stdc++.h>
using namespace std;
string A,B;
const int N=21;
vector<string> a(N),b(N);
unordered_map<string,int> da,db;
int n;
int extend(queue<string>& q, unordered_map<string,int> &da,unordered_map<string,int> &db,vector<string> &a,vector<string> &b){
int d = da[q.front()];
while(q.size()&&da[q.front()]==d){
string t = q.front();
q.pop();
for(int i=0;i<t.size();i++){
for(int j=0;j<n;j++){
if(t.substr(i,a[j].size())==a[j]){
string sub = t.substr(0,i)+b[j]+t.substr(i+a[j].size());
if(db.count(sub)) return db[sub]+da[t]+1;
if(!da.count(sub)){
q.push(sub);
da[sub]=da[t]+1;
}
}
}
}
}
return 11;
}
int bfs(){
if(A==B) return 0;
queue<string> qa,qb;
unordered_map<string,int> da,db;
qa.push(A);
qb.push(B);
da[A]=0,db[B]=0;
int step=0;
while(qa.size()&&qb.size()){
int t;
if(qa.size()>qb.size()){
t=extend(qb,db,da,b,a);
}
else{
t=extend(qa,da,db,a,b);
}
if(t<=10) return t;
if(++step==10) return -1;
}
return -1;
}
signed main(){
cin>>A>>B;
while(cin>>a[n]>>b[n++]);
int t=bfs();
if(t!=-1) cout<<t<<endl;
else puts("NO ANSWER!");
return 0;
}
// 采用单向bfs搜索
# include<bits/stdc++.h>
using namespace std;
string A,B;
const int N=21;
vector<string> a(N),b(N);
unordered_map<string,int> da,db;
int n;
int extend(queue<string>& q, unordered_map<string,int> &da,unordered_map<string,int> &db,vector<string> &a,vector<string> &b){
int d = da[q.front()];
while(q.size()&&da[q.front()]==d){
string t = q.front();
q.pop();
if(da[t]==d){
for(int i=0;i<t.size();i++){
for(int j=0;j<n;j++){
if(t.substr(i,a[j].size())==a[j]){
string sub = t.substr(0,i)+b[j]+t.substr(i+a[j].size());
if(db.count(sub)) return db[sub]+da[t]+1;
if(!da.count(sub)){
q.push(sub);
da[sub]=da[t]+1;
}
}
}
}
}
else break;
}
return 11;
}
int bfs(){
if(A==B) return 0;
queue<string> qa,qb;
unordered_map<string,int> da,db;
qa.push(A);
qb.push(B);
da[A]=0,db[B]=0;
int step=0;
while(qa.size()&&qb.size()){
int t;
if(qa.size()>qb.size()){
t=extend(qb,db,da,b,a);
}
else{
t=extend(qa,da,db,a,b);
}
if(t<=10) return t;
if(++step==10) return -1;
}
return -1;
}
signed main(){
cin>>A>>B;
while(cin>>a[n]>>b[n++]);
int t=bfs();
if(t!=-1) cout<<t<<endl;
else puts("NO ANSWER!");
return 0;
}
A*
题单:
DFS
DFS之搜索顺序
#include<iostream>
using namespace std;
const int N=11;
int ans=N; //记录最优解,求最小因此初始化为最大
int n;
int a[N],st[N];
int ga[N][N]; //存储每组的元素
int gcd(int x,int y){
return y?gcd(y,x%y):x;
}
bool check(int g,int gr,int x){
for(int i=0;i<gr;i++){
if(gcd(ga[g][i],x)>1) return false;
}
return true;
}
//g表示当前是第几组,gr表示当前组的元素个数
//start表示从a数组的哪一个位置开始找放入组内的数,
//从而确定每个数是否需要开新的组,可以恒为零
//
bool dfs(int g,int gr,int start,int tot){
if(g>=ans) return 0;
if(tot==n) ans=g;
int flag = 1;
//如果i从0开始就会死循环,
//不确定是不是因为时间限制,
//不知道有没有死循环
for(int i=start;i<n;i++){
if(!st[i]&&check(g,gr,a[i])){
st[i]=1;
ga[g][gr]=a[i];
dfs(g,gr+1,start+1,tot+1);
st[i]=0; //恢复st[i]是考虑第i个数放在不同组的情况
flag=0;
}
}
//只要新开一组就start=0开始找可以放进新组中的数
//这些数包括回溯恢复的一些数,因为当它们在不同组时,
//和不同的数组成的团可能让新开组的数的后一个数放进去,
//体现在同级的循环上;
if(flag) dfs(g+1,0,0,tot);
}
signed main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
dfs(1,0,0,0);
cout<<ans<<endl;
return 0;
}
DFS之剪枝
排序找最小分支
方案数大于最大数剪枝
枚举小猫,考虑开新车放小猫
#include<bits/stdc++.h>
using namespace std;
const int N=18;
int n,m;
int a[N],sum[N];
int ans = N;
void dfs(int u,int k){
if(k>=ans) return;
if(u==n){ //当枚举完小猫之后,赋k值
ans=k;
return ;
}
for(int i=0;i<k;i++){
if(sum[i]+a[u]<=m){
sum[i]+=a[u];
dfs(u+1,k);
sum[i]-=a[u];
}
}
sum[k]=a[u];
dfs(u+1,k+1);
sum[k]=0;
}
signed main(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
reverse(a,a+n);
dfs(0,0);
cout<<ans<<endl;
return 0;
}
位运算+dfs
#include<bits/stdc++.h>
using namespace std;
const int N=9,M=1<<N;
int col[N],row[N],g[3][3];
int ones[M],lg[M];
char s[100];
void init(){
for(int i=0;i<N;i++){
col[i] = (1<<N) - 1; //不加括号的位运算不能得到结果
row[i] = (1<<N) - 1;
}
for(int i=0;i<3; i++){
for(int j=0 ;j < 3 ; j++){
g[i][j] = (1<<N) - 1;
}
}
}
int lowbit(int x){
return x&-x;
}
void draw(int x,int y,int t,bool flag){
if(flag){
s[x*N+y] = '1'+t;
}
else{
s[x*N+y] = '.';
}
int v=1<<t;
if(!flag) v=-v;
row[x] -= v;
col[y] -= v;
g[x/3][y/3] -= v;
}
int get(int x,int y){
return row[x]&col[y]&g[x/3][y/3];
}
bool dfs(int cnt){
if(!cnt) return true;
int minv=10;
int x,y;
for(int i = 0; i < N ; i++){
for(int j=0; j < N ; j++){
if(s[i*N + j]=='.'){
int v = get(i,j);
if(ones[v]<minv){
minv= ones[v];
x=i,y=j;
}
}
}
}
int v = get(x,y);
for(int i=v;i;i-=lowbit(i)){
int t = lg[lowbit(i)];
draw(x,y,t,true);
if(dfs(cnt-1)) return true;
draw(x,y,t,false);
}
return false;
}
signed main(){
for(int i = 0;i<1<<N;i++){
for(int j=0;j<N ; j++){
ones[i]+=((i>>j) & 1);
}
}
for(int i=0;i<N ;i++) lg[1<<i] = i;
while(cin>>s,s[0]!='e'){
init();
int cnt=0;
for(int i=0,k=0;i<N;i++){
for(int j=0;j<N;j++,k++){
if(s[k]=='.'){
cnt++;
}
else{
int t=s[k]-'1';
draw(i,j,t,true);
}
}
}
dfs(cnt);
puts(s);
}
return 0;
}
二分木棍最小值,向左找,dfs找到可以满足等长的总共木棒数,枚举木棒,将木棍放入,但其实木棍最长也就64,不会爆int,所以从1开始枚举就好了
#include<bits/stdc++.h>
using namespace std;
const int N=70;
int n;
int a[N],v[N];
int sum,length;
//枚举木棒
bool dfs(int u,int cur,int start){
if((u)*length==sum) return true;
if(cur==length) return dfs(u+1,0,0);
for(int i=start;i<n;i++){
if(!v[i]&&cur+a[i]<=length){
v[i]=1;
if(dfs(u,cur+a[i],i+1)) return true;
v[i]=0;
if(!cur||cur+a[i]==length) return false;
int j=i;
while(j<n&&a[i]==a[j]) j++;
i=j-1;
}
}
return false;
}
signed main(){
while(cin>>n,n!=0){
length = 1;
sum=0;
memset(v,0,sizeof v);
for(int i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
sort(a, a + n);
reverse(a, a + n);
while(true){
if(sum%length==0&&dfs(0,0,0)){
cout<<length<<endl;
break;
}
length++;
}
}
return 0;
}