zoukankan      html  css  js  c++  java
  • 关于两道搜索的题目

    T1:

    P2383 狗哥玩木棒

    题目背景

    狗哥又趁着语文课干些无聊的事了...

    题目描述

    现给出一些木棒长度,那么狗哥能否用给出的木棒(木棒全用完)组成一个正方形呢?

    输入格式

    输入文件中的第一行是一个整数n表示测试的组数,接下来n行表示每组的测试数据。 每行的第一个数为m(4<=m<=20),接下来m个数ai(1<=ai<=1000)表示木棒的长度。

    输出格式

    对于每组测试数据,如果可以组成正方形输出“yes”,否则输出“no”。

    输入输出样例

    输入 #1
    3
    4 1 1 1 1 
    5 10 20 30 40 50 
    8 1 7 2 6 4 4 3 5
    输出 #1
    yes
    no
    yes

    说明/提示

    狗哥快抓狂了。


    于是我们要帮助一下抓狂的狗哥。

    对于正方形,其满足的性质为:4边,等长。

    也就是说我们要用木棍组成4边边长为整数的长度完全一样的边。

    先做个判断:木棒总长如果不是4的倍数,直接退出。

    然后我们可以考虑一个策略:

    对于一定的木棒,正方形周长是一定的,为木棒长度总和,于是我们可以进而求出每条边的长度(总长除以4)

    我们可以设置4个“桶”,并且在搜索中尝试着“填入”木棒。“桶”内容量只能少于规定容量(边长)如果4个桶正好被填满,也就意味着所有木棒都使用上了,我们就可以直接弹出,找到了一种情况,输出YES。

    整个题思路就是这样。

    code:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring> 
    using namespace std;
    int read()
    {
        int ans=0;
        char ch=getchar(),last=' ';
        while(ch<'0'||ch>'9')last=ch,ch=getchar();
        while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
        return last=='-'?-ans:ans;
    }
    int n,a[21],l[4],m,sum,judge;
    void dfs(int num)
    {
        if(judge)return;
        if(num>m)
        {
            judge=1;
            return;
        }
        for(int i=0;i<4;i++)
        {
            if(l[i]>=a[num])
            {
                l[i]-=a[num];
                dfs(num+1);
                l[i]+=a[num];
            } 
        }
    }
    
    int main(){
    n=read();
    for(int j=1;j<=n;j++)
    {
        judge=0,sum=0;
        memset(a,0,sizeof(a));
        memset(l,0,sizeof(l));
        m=read();
        for(int i=1;i<=m;i++)
        {
            a[i]=read();sum+=a[i];
        }
        if(sum%4!=0)
        {
            printf("no
    ");
            continue;
        } 
        for(int i=0;i<4;i++)
            l[i]=sum/4;
        dfs(1);
        if(judge)
            printf("yes
    ");
        else printf("no
    ");
    }
    return 0;
    } 

    T2:

    P1379 八数码难题

    题目描述

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

    输入格式

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

    输出格式

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

    输入输出样例

    输入 #1
    283104765
    
    输出 #1
    4

    非常经典的一道题。
    对于状态的表示,.每个状态都用3*3的数组表示,但是BFS中需要入队出队,比较麻烦而且空间占用较大,或者是状态压缩,采用一个整数保存状态的数字序列,例如状态1表示为283104765,状态2表示为203184765。
    对于判重:判重的实质就是建立状态数字串(一个int数据)和是否出现(一个bool数据)之间的联系,而STL中刚好提供了map<key,value>这样一种容器,我们可以将状态数字串作为key,是否出现作为value直接建立起状态--是否出现的联系。
    对于搜索方法的选择,我们可以选择dfs,广度优先搜索,A*搜索方法,三种方法相信大家已经熟练掌握(没错找度娘),在此不再赘述。
    code:
    #include<cmath>
    #include<cstdio>
    #include<iostream>
    using namespace std;
    const int d[4]={-1,0,0,1},f[4]={0,-1,1,0},w[9]={2,1,1,1,2,3,3,3,2},z[9]={2,1,2,3,3,3,2,1,1};
    int ans=-1,flag,a[4][4];
    int read()
    {
        int ans=0;
        char ch=getchar(),last=' ';
        while(ch<'0'||ch>'9')last=ch,ch=getchar();
        while(ch>='0'&&ch<='9')ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar();
        return last=='-'?-ans:ans;
    }
    int guess()
    {
        int i,j,sum=0;
        for (i=1;i<4;i++)
            for (j=1;j<4;j++)
                if (a[i][j]) sum+=abs(w[a[i][j]]-i)+abs(z[a[i][j]]-j);
        return sum;
    }
    void dfs(int now,int x,int y)
    {
        if (flag) return;
        if (now>ans) return;
        int v=guess(),i,m,n;
        if (v+now>ans) return;
        if (!v) { flag=1; return; }
        for (i=0;i<4;i++)
        {
            m=x+d[i],n=y+f[i];
            if (m && m<4 && n && n<4)
            {
                swap(a[x][y],a[m][n]);
                dfs(now+1,m,n);
                swap(a[x][y],a[m][n]);
            }
        }
    }
    int main()
    {
        int i,j,x,y;
        for (i=1;i<4;i++)
            for (j=1;j<4;j++)
            {
                a[i][j]=getchar()-48;
                if (!a[i][j]) x=i,y=j;
            }
        while (!flag) ans++,dfs(0,x,y);
        printf("%d
    ",ans);
        return 0;
    }
    搜索是一项重要偏分技能,希望大家熟练掌握。
    完结。


  • 相关阅读:
    Django U2 模型
    Django U0 使用Django
    Django H2 文档查看
    python模块--time模块/os模块/sys模块
    python模块-logging和collections以及random模块
    python-hashlib模块configparser模块logging模块
    python模块--序列化
    python面向对象的特殊方法和单例模式
    python类属性和类方法以及静态方法和反射
    python面向对象的三个特性
  • 原文地址:https://www.cnblogs.com/lbssxz/p/12678683.html
Copyright © 2011-2022 走看看