您的位置:首页 > 编程语言 > C语言/C++

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

2017-04-11 20:30 169 查看
题目:已知有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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: