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;
    }
    
    • 上面大部分是搜索,当然还有剪枝
  • 相关阅读:
    JavaEE——SpringMVC(11)--拦截器
    JavaEE——SpringMVC(10)--文件上传 CommonsMultipartResovler
    codeforces 460A Vasya and Socks 解题报告
    hdu 1541 Stars 解题报告
    hdu 1166 敌兵布阵 解题报告
    poj 2771 Guardian of Decency 解题报告
    hdu 1514 Free Candies 解题报告
    poj 3020 Antenna Placement 解题报告
    BestCoder5 1001 Poor Hanamichi(hdu 4956) 解题报告
    poj 1325 Machine Schedule 解题报告
  • 原文地址:https://www.cnblogs.com/orange-233/p/12200512.html
Copyright © 2011-2022 走看看