zoukankan      html  css  js  c++  java
  • Day1

    搜索

    • 深度优先搜索
      •     事实上,深度优先搜索属于图算法的一种,英文缩写为DFS即 Depth First Search。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次.
            举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束).
            简要说明深度优先搜索的特点:每次深度优先搜索的结果必然是图的一个连通分量.深度优先搜索可以从多点发起.如果将每个节点在深度优先搜索过程中的"结束时间"排序(具体做法是创建一个list,然后在每个节点的相邻节点都已被访问的情况下,将该节点加入list结尾,然后逆转整个链表),则我们可以得到所谓的"拓扑排序",即topological sort
    • 广度优先搜索

    八皇后

    题目描述

    一个如下的(6*6)的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行、每列有且只有一个,每条对角线(包括两条主对角线的所有平行线)上至多有一个棋子。

    ![八皇后][1]

    上面的布局可以用序列(2 4 6 1 3 5)来描述,第(i)个数字表示在第&i&行的相应位置有一个棋子,如下:

    行号 (1 2 3 4 5 6)

    列号 (2 4 6 1 3 5)

    这只是棋子放置的一个解。请编一个程序找出所有棋子放置的解。
    并把它们以上面的序列方法输出,解按字典顺序排列。
    请输出前 3 个解。最后一行是解的总个数。

    输入格式

    一行一个正整数 n,表示棋盘是 n×n 大小的。

    输出格式

    前三行为前三个解,每个解的两个数字之间用一个空格隔开。第四行只有一个数字,表示解的总数。

    输入

    6
    

    输出

    2 4 6 1 3 5
    3 6 2 5 1 4
    4 1 5 2 6 3
    4
    

    说明/提示

    【数据范围】
    对于(100%)的数据,6 le n le 136≤n≤13。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    int a[25];
    int n, ans=0;
    bool vis[25];
    void dfs(int x) 
    {
    	if(x==n+1)
    	{
    		ans++;
    		if(ans<=3)
    		{
    			for(int i=1; i<=n; i++) printf("%d ", a[i]);
    			putchar('
    ');
    		}
    		return ;
    	}
    	for(int i=1; i<=n; i++)
    	{
    		if(vis[i]==1) continue;
    		bool ok=1;
    		for(int j=1; j<x; j++)
    		{
    			if(abs(x-j)==abs(i-a[j]))
    			{
    				ok=0;
    				break;
    			}
    		}
    		if(ok)
    		{
    			a[x]=i;
    			vis[i]=1;
    			dfs(x+1);
    			vis[i]=0;
    		}
    	}
    	return ;
    }
    int main()
    {
    	scanf("%d", &n);
    	dfs(1);
    	printf("%d ", ans);
    	return 0;
    }
    

    八数码

    题目描述

    在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

    输入格式

    输入初始状态,一行九个数字,空格用0表示

    输出格式

    只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

    输入

    283104765
    

    输出

    4
    
    #include <cstdio>
    #include<map>
    #include<queue>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll dx[]={-1,0,0,1}, dy[]={0,-1,1,0};
    ll n;
    bool check(int nx, int ny)
    {
        return(nx<0||ny<0||nx>2||ny>2);
    }
    int main()
    {
        scanf("%lld", &n);
        queue<ll> q;
        q.push(n);
        map<ll, ll> m;
        m[n] = 0;
        while(!q.empty())
        {
            int u = q.front(); 
            int c[3][2], f=0, g=0, n=u; q.pop();
            if(u == 123804765) break;
            for(ll i=2; i>=0; i--)
            {
                for(ll j=2; j>=0; j--)
                {
                    c[i][j] = n%10, n/=10;
                    if(!c[i][j]) f=i, g=j;
                }
            }//状态转移
            for(ll i=0; i<4; i++)//移动
            {
                ll nx=f+dx[i], ny=g+dy[i], ns=0;
                if(check(nx, ny)) continue; 
                swap(c[nx][ny], c[f][g]);
                for(ll i=0; i<3; i++)
                {
                    for(ll j=0; j<3; j++) ns = ns*10+c[i][j];
                    {
                        if(!m.count(ns))
                        {
                            m[ns] = m[u]+1;
                            q.push(ns);
                        }
                        swap(c[nx][ny], c[f][g]);
                    }
                }
            }
        }
        printf("%d", m[123804765]);
        return 0;
    }
    

    生日蛋糕

    题目背景

    7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层

    生日蛋糕,每层都是一个圆柱体。

    设从下往上数第i(1<=i<=M)层蛋糕是半径为(R_i),高度为(H_i)的圆柱。当i<M时,要求(R_i>R_{i+1})(H_i>H_{i+1})
    由于要在蛋糕上抹奶油,为尽可能节约经费,我们希望蛋糕外表面(最下一层的下底面除外)的面积Q最小。
    (Q= Sπ)
    请编程对给出的N和M,找出蛋糕的制作方案(适当的Ri和Hi的值),使S最小。

    (除Q外,以上所有数据皆为正整数)

    题目描述

    ![生日蛋糕][3]

    输入格式

    有两行,第一行为N(N<=20000),表示待制作的蛋糕的体积为Nπ;第二行为M(M<=15),表示蛋糕的层数为M。

    输出格式

    仅一行,是一个正整数S(若无解则S=0)。

    输入

    100
    2
    

    输出

    68
    
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    int a[21], b[21], m, n, ans; 
    void search(int v, int s, int p, int r, int h)
    {
        int hh;
        if (p == 0)
        {
        	if (v==n && s<ans)//判断是否符合要求并得到更优解
                ans = s;//更新
            return ;
        }
        if(v+b[p-1] > n) return ;//体积超出 
        if(s+a[p-1] > ans) return ;//表面积超出 
        if(2*(n-v)/r+s >= ans)  return; //当前的表面积+余下的侧面积>当前最优值
           	 							//剩余表面积FS>=2*V剩/r   
            							//若FS+s>=ans 则不符合 
        for(int i=r-1; i>=p; i--)//枚举上一层的半径
        {
            if(p == m) s = i*i;
            hh = min((n-v-b[p-1])/(i*i),h-1);
            for(int j=hh; j>=p; j--)//枚举上一层的高
            search(v+i*i*j, s+2*i*j, p-1, i, j);
        }
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        ans = 2147483647;
        a[0] = b[0] = 0;
        for(int i = 1; i<21; i++)
        {
    		a[i] = a[i-1]+2*i*i;//第i层使用的最大表面积 
            b[i] = b[i-1]+i*i*i;//第i层使用的最大体积 
        }
        search(0, 0, m, n+1, n+1);
        if(ans == 2147483647) printf("0");
        else printf("%d", ans);
        return 0;
    }
    
    • 上面大部分是搜索,当然还有剪枝
  • 相关阅读:
    Pytest学习之 autouse=True,自动调用fixture功能
    Pytest学习之xfail使用
    Pytest学习之use fixtures
    python
    python
    python
    python
    python
    python
    python
  • 原文地址:https://www.cnblogs.com/orange-233/p/12200512.html
Copyright © 2011-2022 走看看