回溯法练习【BFS/DFS】

1.N皇后问题
2.油田问题
3.素数环问题
4.马踏棋盘问题
5.图的m着色问题
6.01背包问题
7.TSP问题

【Code-1:输出N皇后方案和个数】

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 105;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
int a[maxn],b[maxn],c[maxn],mp[maxn][maxn];
int n,cnt;
void print()
{
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            printf("%d ",mp[i][j]);
        printf("
");
    }

}
int dfs(int i)
{
    for(int j=1;j<=n;j++)
    {
        if(!a[j] && !b[i-j+n] && !c[i+j])
        {
            mp[i][j]=i;
            a[j]=b[i-j+n]=c[i+j]=1;

            if(i==n)
            {
                print();
                printf("
");
                cnt++;
            }
            else
            {
                dfs(i+1);
            }

            mp[i][j]=0;
            a[j]=b[i-j+n]=c[i+j]=0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    printf("%d
",cnt);
}

【HDU-2553-N皇后输出方案数/预处理打表】:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 105;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
int a[maxn];
int cnt=0;
int vis[3][maxn];
int n;
void dfs(int i)
{
    if(i==n+1)
    {
        cnt++;
        return ;
    }
    for(int j=1;j<=n;j++)
    {
        if(!vis[0][i-j+n] && !vis[1][j] && !vis[2][i+j])
        {
            vis[0][i-j+n] = vis[1][j] = vis[2][i+j] = 1;
            dfs(i+1);
            vis[0][i-j+n] = vis[1][j] = vis[2][i+j] = 0;
        }
    }
}


int main()
{
    for(n=1;n<=10;n++)
    {
        memset(vis,0,sizeof(vis));
        cnt=0;
        dfs(1);
        a[n]=cnt;
    }
    while(~scanf("%d",&n),n)
    {
        printf("%d
",a[n]);
    }

}

【Code-2】:HDU 1241

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 105;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
//int dir[8][2]={ {0,1},{1,-1},{-1,0},{-1,-1},{-1,0},{-1,1},{0,1},{1,1} };
int dir[8][2]={1,0,-1,0,0,1,0,-1,1,1,-1,-1,1,-1,-1,1};
char mp[maxn][maxn];
int n,m;
int ok(int x,int y)
{
    if(x>=0 && y>=0 && x<n && y<m && mp[x][y]=='@')
        return 1;
    return 0;
}
void dfs(int x, int y)
{
    mp[x][y]='*';//把找到的@变为*,以免重复搜索
    for(int i=0;i<8;i++)
    {
        x=x+dir[i][0];
        y=y+dir[i][1];
        if(ok(x,y))
        {
            dfs(x,y);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m),n&&m)
    {
        //getchar();
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",mp[i]);
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(mp[i][j]=='@')
                {
                    dfs(i,j);
                    cnt++;
                }
            }
        }
        printf("%d
",cnt);
    }
}
/*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
*/

【Code-3-素数环】:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 105;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;
int n,cnt;
int vis[maxn];
bool isp(int n)
{
    if(n<=1) return 0;
    else
    {
        for(int i=2;i<=sqrt(n);i++)
        {
            if(n%i==0) return 0;
        }
    }
    return 1;
}
int a[maxn];
/*
int print()
{
    cnt++;
    //printf("(%d)
",cnt);
    for(int j=1;j<=n;j++)
        printf("%d ",a[j]);
    printf("
");
}
*/
void dfs(int cur)
{

    if(cur>n && isp(a[1]+a[n]))
    {
        cnt++;
        for(int i=1;i<=n;i++)
            printf("%d ",a[i]);
        printf("
");
    }
    else
    {
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0 && isp(i+a[cur-1]))
            {
                a[cur]=i;
                vis[i]=1;
                dfs(cur+1);
                vis[i]=0;
            }
        }
    }
}

int main()
{
    scanf("%d",&n);
    memset(a,0,sizeof(a));
    dfs(1);
    printf("Total sum is %d
",cnt);
}

【Code-4-骑士周游】:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 50;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;

int n,m;
int cnt;
int vis[maxn][maxn];
int fx[8]={-1,1,-2,2,-2,2,-1,1};
int fy[8]={-2,-2,-1,-1,1,1,2,2};
int a[maxn][maxn];
int f=0;
struct node
{
    int x,y;
    node(int a=0,int b=0):x(a),y(b){}
}path[maxn];

int ok(int x,int y)
{
    if(x>=1 && y>=1 && x<=n && y<=m && !vis[x][y] && !f)
        return 1;
    return 0;
}

void print()
{
    for(int i=1;i<=n*m;i++){
            int x=path[i].x;
            int y=path[i].y;
            printf("%d %d
",y,x); //输出坐标
        }
}
void dfs(int x, int y, int d)
{
    path[d]=node(x,y);
    if(d==n*m)
    {
        f=1;
        return ;
    }
    for(int i=0;i<8;i++)
    {
        int xx=x+fx[i];
        int yy=y+fy[i];
        if(ok(xx,yy))
        {
            vis[xx][yy]=1;
            dfs(xx,yy,d+1);
            vis[xx][yy]=0;
        }
    }

}
int main()
{
    f=0;
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    vis[1][1]=1;
    dfs(1,1,1);
    if(!f) puts("No");
    else print();
}

【Code-5:洛谷-图的m着色问题】

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 50;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;

int n,m;
int a[maxn][maxn],c[maxn];
int sum=0;

int ok(int i)
{
    for(int j=1;j<=n;j++)
    {
        if(a[i][j] && c[i]==c[j])
            return 0;
    }
    return 1;
}

void dfs(int cur)
{
    if(cur==n+1)
    {
        sum++;
        for(int i=1;i<=n;i++)
            printf("%d ",c[i]);
        printf("
");
        return ;
    }
    else
    {
        for(int i=1;i<=m;i++)
        {
            c[cur]=i;
            if(ok(cur))
            {
                dfs(cur+1);
            }
            c[cur]=0;
        }
    }
}

int main()
{
    int x,y,k;
    scanf("%d%d%d",&n,&k,&m);
    while(k--)
    {
        scanf("%d%d",&x,&y);
        a[x][y]=a[y][x]=1;
    }
    dfs(1);
    if(!sum) puts("No");
    else printf("%d
",sum);
}
/*
5 8 4
1 2
1 3
1 4
2 3
2 4
2 5
3 4
4 5

48
*/

【Code6-01背包回溯版】:

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 2*1e5+5;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;

//int v[maxn],w[maxn];
int n,c,cp,bestp;//物品数、背包大小、当前价值、最优价值
int x[maxn],bestx[maxn];//当前解、最优解
struct node
{
    int v,w;//价值、重量
}a[maxn];
bool cmp(node a, node b)
{
    return a.v*b.w > b.v*a.w;
}
void print()
{
    for(int i=0;i<n;i++)
        printf("%d ",bestx[i]);
    printf("
"); return ;
}
void dfs(int cur)
{
    if(cur>=n)
    {
        if(bestp<cp)
            bestp=cp;
        for(int i=0;i<n;i++)
            bestx[i]=x[i];
        //print();
    }
    else
    {
        if(a[cur].w <= c)
        {
            x[cur]=1; cp+=a[cur].v; c-=a[cur].w;
            dfs(cur+1);
            x[cur]=0; c+=a[cur].w; cp-=a[cur].v;
        }
        x[cur]=0;
        dfs(cur+1);
    }
}

int main()
{
    scanf("%d%d",&n,&c);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i].v);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i].w);
    sort(a,a+n,cmp);
    dfs(0);
    printf("%d
",bestp);
}
/*
5 10
6 3 6 5 4
2 2 4 6 5

最优价值 15
放入   1 2 3


3 30
16 10 13
45 20 25
*/

【输出路径版】

#include<bits/stdc++.h>
using namespace std;
typedef long long  ll;
const int maxn = 2*1e5+5;
const ll INF = 2147483647;
typedef pair<ll ,int> pli;

int w[maxn];  
int v[maxn];  
int best_ans[maxn], ans[maxn];  
int cw, cv, n, max_w, max_v ;
void print()  
{  
    printf("%d
",max_v);  
    for(int i=0;i<n;i++)  
        printf("%d ",best_ans[i]);  
    printf("
");  
}  
  
void DFS(int step,int cw,int cv)  
{  
    if(step>=n)  
    {  
        if(cv > max_v)  
        {   
            max_v = cv;
            for(int i=0;i<n;i++)  
                best_ans[i] = ans[i];  
        }  
    }  
    else  
    {  
        if(cw >= w[step])  
        {   
            ans[step] = 1;  cv += v[step]; cw -= w[step];  
            DFS(step+1,cw,cv);  
            ans[step] = 0;  cv -= v[step]; cw += w[step]; 
        }  
        ans[step]=0;
        DFS(step+1,cw,cv);  
    }  
}  
  
void init()  
{  
    max_v = 0;  
    for(int i=0;i<n;i++)  
        ans[i] = 0;  
    max_v = 0;
}  
  
int main()  
{  
    while(scanf("%d%d",&n,&max_w)!=EOF)  
    {  
        for(int i=0;i<n;i++)  
            scanf("%d",&v[i]);  
        for(int j=0;j<n;j++)  
            scanf("%d",&w[j]);  
        init();  
        DFS(0,max_w,0);  
        print();       
    }  
    return 0; 
}  
/*
5 10
6 3 6 5 4
2 2 4 6 5

*/
原文地址:https://www.cnblogs.com/Roni-i/p/9138706.html