蓝桥杯 B组c++第四题 6*6正方形裁剪猜想
2017-04-11 20:30
169 查看
题目:已知有6*6的正方形纸,裁剪一次使得剪出来的两块一模一样,问总共有多少种可能
现在答案还没出来,但是大概有一个思路,先与大家分享,如果有问题欢迎大家指出~
首先这个题目的纯暴力肯定是不行的,到了比赛的后程,我观察到了一点点规律,我们假设要裁剪出左边和右边一样的情况,假设是简单的梯形,我们发现一定是”中心对称”的。
直接说就是如果我们想下面一样左右翻转对称,只要暴力求前三行,那么后三行根据中心对称就可以得到!
![](https://img-blog.csdn.net/20170411201221187?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzUwNzg2MzE=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
1.前三行用了类似状压的思路建图,暴力模拟前三行,然后推出全图
2.然后检验连通性,我们假设两种颜色的分别用0,1代表,两次dfs检查连通性,如果连通块大小都是18的话说明可能是答案
3.然后我们要考虑可能的去重,无非就是旋转0°、90°、180°、270°。我们用map
然后上代码,如果思路有问题希望大牛指正啊!
思路尚未验证,如有问题求大牛指正
现在答案还没出来,但是大概有一个思路,先与大家分享,如果有问题欢迎大家指出~
首先这个题目的纯暴力肯定是不行的,到了比赛的后程,我观察到了一点点规律,我们假设要裁剪出左边和右边一样的情况,假设是简单的梯形,我们发现一定是”中心对称”的。
直接说就是如果我们想下面一样左右翻转对称,只要暴力求前三行,那么后三行根据中心对称就可以得到!
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; }
相关文章推荐
- 第六届蓝桥杯A组C/C++ 第四题 格子中输出
- 2014 蓝桥杯 预赛 c/c++ 本科B组 第四题:史丰收速算(7' )
- 2014 蓝桥杯 预赛 c/c++ 本科B组 第四题:史丰收速算(7' )
- 2018年第九届蓝桥杯【C++省赛B组】【第四题:测试次数】
- 2016第七届蓝桥杯C/C++ B组省赛第四题
- 2017第八届蓝桥杯C/C++ B组省赛第四题 dfs
- 第八届蓝桥杯C++B组第四题:方格分割
- 第六届蓝桥杯C++B组第四题:格子中输出
- 第六届蓝桥杯C/C++A组第四题解答
- 第八届蓝桥杯c++大学A组(省赛)——第四题
- 2016第七届蓝桥杯C++B组第四题:快速排序
- 2013 蓝桥杯第四届c/c++B组 解题报告(完全解决第四题,代码有点长....)
- (2017)第八届蓝桥杯大赛个人赛省赛(软件类) C/C++ 大学A组 题解(第三题和第四题)
- 【Java实现】2012蓝桥杯C++高职组第四题——巧排扑克牌
- 2014蓝桥杯本科B组C/C++第四题【史丰收速算】
- 蓝桥杯第五届C/C++A组第四题 史丰收速算
- 蓝桥杯 c /c++ A 组 第四题:第几个幸运数
- 2014年第五届蓝桥杯C++B组第四题:史丰收速算
- 【快速排序】(2016)第七届蓝桥杯省赛 C/C++ A组 题解(第四题)
- 蓝桥杯-夺冠概率 C++实现