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;
    }
    
  • 相关阅读:
    85. Maximal Rectangle
    120. Triangle
    72. Edit Distance
    39. Combination Sum
    44. Wildcard Matching
    138. Copy List with Random Pointer
    91. Decode Ways
    142. Linked List Cycle II
    异或的性质及应用
    64. Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/OFSHK/p/13809889.html
Copyright © 2011-2022 走看看