浏览器标题切换
浏览器标题切换end

蓝桥杯2016初赛 - 剪邮票 - DFS

题目链接

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

题面

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

求多少种剪法。

思路

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

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

undefined

这种走法(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;
}
posted @   抓水母的派大星  阅读(173)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示