zoukankan      html  css  js  c++  java
  • 蓝桥杯2016初赛

    题目链接

    http://oj.ecustacm.cn/status.php?problem_id=&user_id=18112810106&language=-1&jresult=-1&csrf=vgEBiW8Bo4QFjLAUnYyt62Vwo2URDZ6T

    题面

    如下图, 有12张连在一起的12生肖的邮票。现在你要从中剪下5张来,要求必须是连着的。(仅仅连接一个角不算相连)。

    求多少种剪法。

    思路

    间接相当于求路径/条数/方法数等,所以我们可以很容易的想到利用 DFS 来做。

    但是我没有考虑到的是,该题的图三(下图):

    这种走法(T型呀、Π型呀等),DFS是走不到的,DFS最直观的就是一条路走到头,所以可以说,DFS不会拐弯,所以题目给定的第三幅图其实直接用一般的DFS模板我

    们解出来会比正确答案少,好像解出来是八十几来着,但是正确的答案是116。

    所以这题就是DFS变形,因为得另外开一个数组去记录路径,网上有好多方法,我参考的是直接通过二进制位移,就是每次DFS的时候如果发现满足条件5的就把整个图都遍历一下,把book为真的直接 x<<=1 就行(这里优先级<<大!?)

    PS:蓝桥杯都变形了吗……

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define inf 0x3f3f3f3f
    
    int a[5][5],ans;
    bool book[5][5],book1[100010];
    int to[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};
    
    void dfs(int cnt)
    {
        if(cnt==5) // 不要急着return,对这条路径进行处理(记录)
        {
            int w=0;
            for(int i=1; i<=3; i++)
            {
                for(int j=1; j<=4; j++)
                {
                    w+=book[i][j];
                    w<<=1; //不加()?
                }
            }
            if(!book1[w])
            {
                ans++;
                book1[w]=1;
                // return;
            }
            return;
        }
    //        for(int i=0; i<4; i++) //不知道直接 *k是否可以?
    //        {
    //            for
    //        } //这里写的不是遍历方向,方向放在两个for里面写
    
        for(int i=1; i<=3; i++)
        {
            for(int j=1; j<=4; j++)
            {
                if(book[i][j]) // *** don't forget 不是==0
                {
                    for(int k=0; k<4; k++)
                    {
                        int tx=i+to[k][0];
                        int ty=j+to[k][1]; // 这里用xy,因为1没有传入xy,2该图直接用对应坐标即可
                        if(tx>=1&&tx<=3&&ty>=1&&ty<=4&&!book[tx][ty])
                        {
                            book[tx][ty]=1;
                            dfs(cnt+1);
                            book[tx][ty]=0;
                        }
                    }
                }
            }
        }
    }
    
    int main()
    {
        ans=0;
        for(int i=1; i<=3; i++)
        {
            for(int j=1; j<=4; j++)
            {
                book[i][j]=1;
                dfs(1); // 表示长度为5中长度为1的已经搜到了
                book[i][j]=0; //因为是搜索路径,所以DFS需要标记+取消标记
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

    我的DFS失败代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define inf 0x3f3f3f3f
    
    int a[5][5],cnt,ans;
    bool book[5][5];
    int to[4][2]= {{-1,0},{0,1},{1,0},{0,-1}};
    
    void dfs(int x,int y,int ss)
    {
        if(ss>=5) return ;
        for(int i=0; i<4; i++)
        {
            for(int k=0; k<=4; k++)
            {
                int tx=x+to[i][0]*k;
                int ty=y+to[i][1]*k;
                if(tx>=1&&tx<=3&&ty>=1&&ty<=4&&!book[tx][ty])
                {
                    book[tx][ty]=1;
                    dfs(tx,ty,ss+1);
                    book[tx][ty]=0;
                }
            }
        }
    }
    
    int main()
    {
        cnt=0;
        for(int i=1; i<=3; i++)
        {
            for(int j=1; j<=4; j++)
                a[i][j]=++cnt;
        }
        for(int i=1; i<=3; i++)
        {
            for(int j=1; j<=4; j++)
            {
                memset(book,0,sizeof(book));
                ans++;
                dfs(i,j,0);
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    算法作业实验三
    牛客练习赛53 B 美味果冻
    牛客练习赛53 C 富豪凯匹配串
    bitmat
    牛客挑战赛33 B 鸽天的放鸽序列
    树状数组
    线段树
    2019牛客国庆集训派对day7 A 2016
    背包
    作业三 -并查集
  • 原文地址:https://www.cnblogs.com/OFSHK/p/13809889.html
Copyright © 2011-2022 走看看