zoukankan      html  css  js  c++  java
  • HZNUACM寒假集训Day3小结 搜索

          简单搜索

    1.DFS

     UVA 548 树

     1.可以用数组方式实现二叉树,在申请结点时仍用“动态化静态”的思想,写newnode函数 

     2.给定二叉树的中序遍历和后序遍历,可以构造出这棵二叉树,方法是根据后序遍历找到根,然后在中序遍历中找到树根,从而找出左右子树的结点列表然后递归 构造左右子树

     3.注意这里输入的模板,用stringstream会方便

    #include<iostream>
    #include<string>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<sstream>
    #include<cstdio>
    #define INF 0x3f3f3f3f
    const int maxn = 1e6 + 5;
    const double PI = acos(-1.0);
    typedef long long ll;
    using namespace std;
    
    const int maxv = 10000 + 10;
    int in_order[maxv], post_order[maxv], lch[maxv], rch[maxv];
    int n;
    
    bool read_list(int* a) {
        string line;
        if (!getline(cin, line)) return false;
        stringstream ss(line);
        n = 0;
        int x;
        while (ss >> x) a[n++] = x;
        return n > 0;
    }
    
    int build(int L1, int R1, int L2, int R2) {
        if (L1 > R1) return 0;
        int root = post_order[R2];
        int p = L1;
        while (in_order[p] != root) p++;
        int cnt = p - L1;
        lch[root] = build(L1, p - 1, L2, L2 + cnt - 1);
        rch[root] = build(p + 1, R1, L2 + cnt, R2 - 1);
        return root;
     }
    
    int best, best_sum;
    
    void dfs(int u, int sum) {
        sum += u;
        if (!lch[u] && !rch[u]) {
            if (sum < best_sum || (sum == best_sum && u < best)) {
                best = u;
                best_sum = sum;
            }
        }
        if (lch[u]) dfs(lch[u], sum);
        if (rch[u]) dfs(rch[u], sum);
    }
    
    int main() {
        while (read_list(in_order)) {
            read_list(post_order);
            build(0, n - 1, 0, n - 1);
            best_sum = 10000000;
            dfs(post_order[n - 1], 0);
            cout << best << "\n";
        }
        return 0;
    }

        2000提高组-C  单词接龙  

        用substr判断能否接上

    #include<iostream>
    #include<string>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<sstream>
    #include<cstdio>
    #define INF 0x3f3f3f3f
    const int maxn = 1e6 + 5;
    const double PI = acos(-1.0);
    typedef long long ll;
    using namespace std;
    
    string s[25];
    int vis[25];
    int Max=-1;
    int n;
    
    void dfs(string x, int len) {
        Max = max(Max, len);
        for (int i = 1; i <= n; i++) {
            if (vis[i] == 2) continue;
            int l1 = x.length();
            int l2 = s[i].length();
            int p = 1;
            while (p < min(l1, l2))
                if (x.substr(l1 - p) == s[i].substr(0, p)) break; else p++;
            if (p < min(l1, l2)) {
                vis[i]++;
                dfs(x.substr(0,l1-p)+s[i], len + s[i].length()-p);
                vis[i]--;
            }
        }
    }
    
    int main() {
        std::ios::sync_with_stdio(0);
        cin.tie(0);
    
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> s[i];
        cin >> s[0];
        s[0] = "0" + s[0];
        dfs(s[0], s[0].length());
        cout << Max-1;
        return 0;
    }

        回溯    N皇后问题 http://acm.hdu.edu.cn/showproblem.php?pid=2553

       

    #include<iostream>
    #include<string>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<sstream>
    #include<cstdio>
    #define INF 0x3f3f3f3f
    const int maxn = 1e6 + 5;
    const double PI = acos(-1.0);
    typedef long long ll;
    using namespace std;
    
    int x[15], y[15];   //x[i]为第i行所在的列
    int n1, ans;
    
    bool place(int k) {
        for (int i = 1; i < k; i++) {
            if (abs(x[i] - x[k]) == abs(i - k) || x[i] == x[k]) return false;
        }
        return true;
    }  //判断位置是否可行
    void dfs(int a) {   //遍历到a行,共n1行
        if (a > n1) ans++;    //已经放了n1个皇后
        else {
            for (int i = 1; i <= n1; i++) {
                x[a] = i;
                if (place(a)) dfs(a + 1);
            }
        }
    }
    
    int main() {
        int n;
        for (int i = 1; i <= 10; i++) {
            ans = 0;
            n1 = i;
            dfs(1);
            y[i] = ans;
        }
        while (scanf("%d", &n), n) {
            printf("%d\n", y[n]);
        }
        return 0;
    }

        BFS

        BFS通常用队列实现,开一个vis数组标记是否访问过

     

          如Catch That Cow http://poj.org/problem?id=3278   如果用DFS会TLE,考虑DFS

          

    #include<iostream>
    #include<string>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<map>
    #include<set>
    #include<algorithm>
    #include<queue>
    #include<stack>
    #include<sstream>
    #include<cstdio>
    #define INF 0x3f3f3f3f
    const int maxn = 1e6 + 5;
    const double PI = acos(-1.0);
    const int N = 200100;
    typedef long long ll;
    using namespace std;
    
    int n, k;
    struct Node {
        int x;
        int step;
    };
    queue<Node> q;
    int vis[N];
    
    void bfs() {
        int X, Step;
        while (!q.empty()) {
            Node Q = q.front();
            q.pop();
            X = Q.x;
            Step = Q.step;
            if (X == k) {
                printf("%d", Step);
                return;
            }
            if (X >= 1 && (!vis[X - 1])) {
                Node p;
                vis[X - 1] = true;
                p.x = X - 1;
                p.step = Step + 1;
                q.push(p);
            }
            if (X <= k && (!vis[X + 1])) {
                Node p;
                vis[X + 1] = true;
                p.x = X + 1;
                p.step = Step + 1;
                q.push(p);
            }
            if (X <= k && (!vis[X * 2])) {
                Node p;
                vis[X * 2] = true;
                p.x = X * 2;
                p.step = Step + 1;
                q.push(p);
            }
        }
    }
    
    int main() {
        scanf("%d%d", &n, &k);
        Node NODE ;
        NODE.x = n;
        NODE.step = 0;
        q.push(NODE);
        bfs();
        return 0;
    }

        回溯法一般是要找到一个(或者所有)满足约束的解(或者某种意义下的最优解),而状态空间搜索一般是要找到一个从初始状态到终止状态的路径  

        路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条从初始状态到终止状态的最优路径,而不像回溯法那样找到一个符合某些条件的解。

       八数码问题

    #include<iostream>
    #include<map>
    #include<queue>
    
    using namespace std;
    
    queue<int>Q;
    map<int,int>vis;//标记数组
    map<int,int>step;//记录到这种状态的步数
    
    int dir[4][2]={-1,0,0,1,1,0,0,-1};//上,右,下,左
    int mat[3][3];
    int state;//输入的初始状态
    int r,c;
    
    void input()//输入数据并将矩阵转化为一个九位整数
    {
        int tmp=0;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            {
                cin>>mat[i][j];
                tmp=tmp*10+mat[i][j];
            }
        state=tmp;
    }
    
    bool can_move(int u,int d)//判断是否可以走
    {
        for(int i=2;i>=0;i--)//将整数变回矩阵才好判断
        {
            for(int j=2;j>=0;j--)
            {
                mat[i][j]=u%10;
                u/=10;
                if(mat[i][j]==0)
                {
                    r=i;
                    c=j;
                }
            }
        }
        //判断四个方向是否能走
        if((d==0&&r==0)||(d==1&&c==2)||(d==2&&r==2)||(d==3&&c==0))
            return 0;
        return 1;
    }
    
    int move_to(int u,int d)//返回从状态u走到的状态
    {
        int tmp=0;
        int nr=r+dir[d][0];
        int nc=c+dir[d][1];
        mat[r][c]=mat[nr][nc];
        mat[nr][nc]=0;
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
                tmp=tmp*10+mat[i][j];
        }
        return tmp;
    }
    
    int bfs(int s)
    {
        Q.push(s);
        vis[s]=1;
        step[s]=0;
        while(Q.size())
        {
            int u,v;
            u=Q.front();
            Q.pop();
            if(u==123456780)
                return step[u];
            for(int i=0;i<4;i++)
            {
                if(can_move(u,i))
                {
                    v=move_to(u,i);
                    if(!vis[v])
                    {
                        vis[v]=1;
                        step[v]=step[u]+1;
                        Q.push(v);
                    }
                }
            }
        }
        return -1;
    }
    
    int main()
    {
        input();
        int ans=bfs(state);
        cout<<ans<<endl;
        return 0;
    }
    
    
    
    
    

         拓扑排序 

         不包含有向环的有向图称为有向无环图(DAG),如果图中存在有向环,则不存在拓扑排序

  • 相关阅读:
    (转)排序算法——归并排序与递归
    在serviceImpl里使用自身的方法
    hibernate manytoone中的lazy EAGER
    autowire异常的三个情况
    (转)js的call和apply
    mysql创建外键出错(注意数据库表字段排序)
    easyui datagrid
    ava.lang.NullPointerException的一般解决方法
    spring简单事务管理器
    关于使用注解出现BeanCreationException或者NameNotFoundException的解决方法
  • 原文地址:https://www.cnblogs.com/hznumqf/p/12243776.html
Copyright © 2011-2022 走看看