蓝桥杯真题 剪邮票 题解

42 篇文章 2 订阅
11 篇文章 0 订阅

题目:
如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。 (仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

这里写图片描述

这里写图片描述

这里写图片描述

正确答案在下面!!
(错误答案大神们请无视….)

Wrong Answer:
错因:这道题是不能边用dfs边判断,
比如图3的情况就不能考虑到:第2行第1列的格子可以选,
但是我写的代码里面就不能选,因为它的上面和左面的格子都没有被选过
而且!!我一开始的判断代码是错的,因为我判断了它左上角和右上角的格子,大概是判断代码写习惯了
搞了好几天才终于知道错误原因,( ! ^ ! )

//剪邮票
//wrong answer
#include<bits/stdc++.h>
using namespace std;
int cnt = 0;
bool selected[5][5];
int row,col,num;//num:要剪下来的个数 

bool alright(int x, int y,int cur){
    if(cur == 0) return true;
    int xx = x  - 1,yy = y - 1;
    //上面 
    if(xx >= 1){
        if(selected[xx][y]) return true;
    }
    //左面
    if(yy >= 1){
        if(selected[x][yy]) return true;
    }
    return false;

/*wrong answer 
    for(int dx = -1; dx <= 1; ++dx){
        for(int dy = -1; dy <= 1; ++dy){
            int xx = x + dx, yy = y + dy;
            if(xx < 1 || yy < 1 || xx > row || yy > col) continue;
            if(dx != 0 || dy != 0){
                if(selected[xx][yy]) return true;
            }
        }
    }

    return false;

    */
}

void dfs(int x, int y,int cur){
    if(cur == num){
        cnt++;
        return ;
    }
    if(cur < num && x > row) return ;

    //选
    if(alright(x, y,cur)){
        selected[x][y] = true;
        if( y == col) dfs(x + 1,1,cur + 1);
        else dfs(x, y + 1, cur + 1);
        selected[x][y] = false;
    } 

    //不选 
    selected[x][y] = false;
    if(y == col) dfs(x + 1, 1, cur);
    else dfs(x, y + 1, cur);

}

int main(){
    row = 3;
    col = 4;
    num = 5;
    for(int i = 1; i <= row; ++i){
        for(int j = 1; j <= col; ++j){
            selected[i][j] = false;
        }
    }
    dfs(1,1,0);
    cout<<cnt<<endl;

    return 0;
}

思路:
用DFS;递归深度为格子数(3 * 4 = 12),每个格子有两种可能的选择:选or不选,递归出口为已选择的格子数为5;应该是选完5个格子后再判断是否满足上下左右相邻的条件,不能边选边判断;判断1个连通块包含的格子数用普通递归orDFS(这里我用的普通的递归)
PS:调试是个好东西!输出结果出错时在DFS里面多用下输出调试看看哪步出错

答案:116

Code:

//剪邮票  答案:116 
#include<bits/stdc++.h>
using namespace std;
int cnt = 0;
int selected[5][5];
int row,col,num;//num:要剪下来的个数
bool vis[5][5];
int unitcnt = 0;
int move[4][2] = {{-1, 0}, {0, -1},{0, 1}, {1, 0}};


int getsum(int x, int y){
    if(x < 1 || y < 1 || x > row || y > col) return 0; 
    if(selected[x][y] == 0) return 0;
    if(vis[x][y]) return 0; 
    vis[x][y] = true;
    return  1 + getsum(x - 1, y) + getsum(x, y - 1) + getsum(x + 1,y) + getsum(x, y + 1);
}

void dfs(int x, int y,int cur){

    if(cur == num){
   //   cout<<"cur == num"<<endl; 
        int i,j;
        bool flag = false;
        for(i = 1; i <= row; ++i){
            for(j = 1; j <= col; ++j){
    //          cout<<"selected[] = "<<selected[i][j]<<endl;            
                if(selected[i][j] == 1){
                    flag = true;
                    break;
                }
            }
            if(flag) break;
        }
        for(int k = 1; k <= row; ++k){
            for(int t = 1; t <= col; ++t){
                vis[k][t] = false;
            }
        }
//      cout<<"selected[] = "<<selected[i][j]<<endl;
        if(getsum(i,j) == num) cnt++;
        return ;
    }
    if(cur < num && x > row) return ;


    //选 
    selected[x][y] = 1;
    if( y == col) dfs(x + 1,1,cur + 1);
    else dfs(x, y + 1, cur + 1);
    selected[x][y] = 0;

    //不选 
    selected[x][y] = 0;
    if(y == col) dfs(x + 1, 1, cur);
    else dfs(x, y + 1, cur);

}

int main(){
    row = 3;
    col = 4;
    num = 5;

    for(int i = 1; i <= row; ++i){
        for(int j = 1; j <= col; ++j){
            selected[i][j] = 0;
        }
    }
    dfs(1,1,0);
    cout<<cnt<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值