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

来源:互联网 发布:广州数控编程讲解视频 编辑:程序博客网 时间:2024/06/15 14:12

题目:已知有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;} 
0 0
原创粉丝点击