蓝桥杯 B组c++第四题 6*6正方形裁剪猜想

题目:已知有6*6的正方形纸,裁剪一次使得剪出来的两块一模一样,问总共有多少种可能

现在答案还没出来,但是大概有一个思路,先与大家分享,如果有问题欢迎大家指出~

首先这个题目的纯暴力肯定是不行的,到了比赛的后程,我观察到了一点点规律,我们假设要裁剪出左边和右边一样的情况,假设是简单的梯形,我们发现一定是”中心对称”的。


直接说就是如果我们想下面一样左右翻转对称,只要暴力求前三行,那么后三行根据中心对称就可以得到!

这里写图片描述

1.前三行用了类似状压的思路建图,暴力模拟前三行,然后推出全图
2.然后检验连通性,我们假设两种颜色的分别用0,1代表,两次dfs检查连通性,如果连通块大小都是18的话说明可能是答案
3.然后我们要考虑可能的去重,无非就是旋转0°、90°、180°、270°。我们用map<string,int>mp;做类似hash的表。从四个旋转方向将颜色值链接成一个64长度的字符串,如果在迭代器中四个串都没有出现过,说明没有重复~

然后上代码,如果思路有问题希望大牛指正啊!


思路尚未验证,如有问题求大牛指正

#include<bits/stdc++.h>
using namespace std;
int mapp[7][7],v[7][7];
int check0,check1;
int ans=0,temp=0;
int dir[4][2]={-1,0,1,0,0,-1,0,1};
map<string,int>mp;
int inmap(int x,int y){                     //检验是否在合法的范围之内
    if(x<1||x>6||y<0||y>6) return 0;
    return 1;
}
void dfs(int x,int y,int vvv){              //检验联通块儿大小
    v[x][y]=1;
    if(vvv==0)  check0++;
    else        check1++;
    for(int i=0;i<4;i++){
        if(inmap(x+dir[i][0],y+dir[i][1])&&mapp[x+dir[i][0]][y+dir[i][1]]==vvv&&v[x+dir[i][0]][y+dir[i][1]]==0){
            dfs(x+dir[i][0],y+dir[i][1],vvv);
        }
    }
}
int main(){
    mp.clear();
    for(int s1=0;s1<64;s1++){               //状压暴力前三行
        for(int s2=0;s2<64;s2++){
            for(int s3=0;s3<64;s3++){
                check0=check1=0;
                memset(v,0,sizeof(v));
                memset(mapp,0,sizeof(mapp));
                for(int i=0;i<6;i++){
                    if((s1>>i)&1) mapp[1][i+1]=1;
                    if((s2>>i)&1) mapp[2][i+1]=1;
                    if((s3>>i)&1) mapp[3][i+1]=1;
                }
                for(int i=1;i<=6;i++){      //中心对称求出后三行
                    if(mapp[1][i]==0) mapp[6][7-i]=1;
                    if(mapp[2][i]==0) mapp[5][7-i]=1;
                    if(mapp[3][i]==0) mapp[4][7-i]=1;
                }
                int flag=1;
                for(int i=1;i<=6;i++){      //找到颜色代表值为0的位置并检验联通块的数量
                    for(int j=1;j<=6;j++){
                        if(mapp[i][j]==0){
                            dfs(i,j,0);
                            flag=0;
                            break;
                        }
                    }
                    if(flag==0){
                        break;
                    }
                }
                flag=1;
                for(int i=1;i<=6;i++){      //找到颜色代表值为1的位置并检验联通块的数量
                    for(int j=1;j<=6;j++){
                        if(mapp[i][j]==1){
                            dfs(i,j,1);
                            flag=0;
                            break;
                        }
                    }
                    if(flag==0){
                        break;
                    }
                }
                //cout<<check0<<" "<<check1<<endl;
                if(check0==18&&check1==18){ //当两个颜色联通块儿数量都是18的时候可能是对的
                    temp++;
                    string turn1="",turn2="",turn3="",turn4="";     //构造四个方向的字符串hash值
                    for(int i=1;i<=6;i++){
                        for(int j=1;j<=6;j++){
                            if(mapp[i][j]==1) turn1+="1";
                            else turn1+="0"; 
                        }
                    }
                    for(int i=1;i<=6;i++){
                        for(int j=6;j>=1;j--){
                            if(mapp[j][i]==1) turn2+="1";
                            else turn2+="0"; 
                        }
                    }
                    for(int i=6;i>=1;i--){
                        for(int j=6;j>=1;j--){
                            if(mapp[i][j]==1) turn3+="1";
                            else turn3+="0"; 
                        }
                    }
                    for(int i=6;i>=6;i--){
                        for(int j=1;j<=6;j++){
                            if(mapp[j][i]==1) turn4+="1";
                            else turn4+="0"; 
                        }
                    }
                    if(mp[turn1]==0&&mp[turn2]==0&&mp[turn3]==0&&mp[turn4]==0) mp[turn1]=1; //如果都不存在,肯定不会和已有的图重合
                }
            }
        }
    }
    map<string,int>::iterator it;
    for(it=mp.begin();it!=mp.end();it++){
        if(it->second>0){
            ans++;
        }
    }
    cout<<temp<<endl;
    cout<<ans<<endl;
    return 0;
} 
以下是蓝桥杯中级历年C++: 2019年蓝桥杯省赛真 - 第一:求和 - 第二:小球下落 - 第三:字符串反转 - 第四:图像旋转 - 第五:矩阵计算 - 第六:数字分解 - 第七:排列与合 - 第八:数去重 2018年蓝桥杯省赛真 - 第一:年龄与疾病 - 第二:津津的储蓄计划 - 第三:统计字符 - 第四:拼图游戏 - 第五:简化路径 - 第六:皇后问 - 第七:独立的小球 - 第八:生命游戏 2017年蓝桥杯省赛真 - 第一:简单计算器 - 第二:数字排序 - 第三:大整数加法 - 第四:数字三角形 - 第五:随机数生成器 - 第六:词典 - 第七:数码管 - 第八:磁盘分区 2016年蓝桥杯省赛真 - 第一:猜字母 - 第二:字符串的插入和删除 - 第三:矩阵乘法 - 第四:大数加法 - 第五:图像旋转 - 第六:数列求和 - 第七:矩阵变换 - 第八:货车运输问 2015年蓝桥杯省赛真 - 第一:奇偶排序 - 第二:火车进站 - 第三:二叉树遍历 - 第四:矩阵乘法 - 第五:立方体表面积 - 第六:计算器 - 第七:数独 - 第八:晶体生 2014年蓝桥杯省赛真 - 第一:逆序对 - 第二:小球下落 - 第三:最公共子序列 - 第四:矩阵乘法 - 第五:矩阵计算 - 第六:整数划分 - 第七:排列 - 第八:猜数字 2013年蓝桥杯省赛真 - 第一:计算器 - 第二:数逆序重放 - 第三:图像旋转 - 第四:表达式求值 - 第五:矩阵计算 - 第六:拨钟问 - 第七:递推数列 - 第八:小明放学 2012年蓝桥杯省赛真 - 第一:小明放学 - 第二:求最大子段和 - 第三:数独 - 第四:矩阵计算 - 第五:图像旋转 - 第六:八皇后问 - 第七:矩阵变换 - 第八:单词接龙 2011年蓝桥杯省赛真 - 第一:求最大子段和 - 第二:逆序对 - 第三:数独 - 第四:矩阵计算 - 第五:矩阵变换 - 第六:八皇后问 - 第七:括号匹配 - 第八:火车进站 以上是蓝桥杯中级历年C++,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值