剪邮票
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)比如,下面两个图中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。 请填写表示方案数目的整数。
反思:后来发现有一种情况深搜是搜不到的,如:
欢迎给予优化指导。
如下图, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)比如,下面两个图中,粉红色所示部分就是合格的剪取。
请你计算,一共有多少种不同的剪取方法。 请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:看到题的第一想法是用深搜,遍历一遍,满怀希望的期待着答案,结果GG了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int toX[4]={0,1,0,-1};//上 下 左 右 四个方向
int toY[4]={1,0,-1,0};
int vis[4][5]; //标记数组
int sum;
void dfs(int x, int y, int s){
if( x<0 || x>=3 || y<0 || y>=4) return ;//越界
if(s>5) return ;
if( s == 5 ){
sum++;
return ;
}
int xx,yy;
for(int i=0; i<4; ++i){
xx=x+toX[i];
yy=y+toY[i];
if(vis[xx][yy]==0){
vis[xx][yy]=1;
dfs(xx,yy,s+1);
vis[xx][yy]=0;
}
}
}
int main(){
memset(vis,0,sizeof(vis));
sum=0;
for(int i=0; i<3; ++i){
for(int j=0;j<4; ++j){
vis[i][j]=1;
dfs(i,j,1);
vis[i][j]=0;
}
}
printf("%d\n",sum);//结果是220
return 0;
}
反思:后来发现有一种情况深搜是搜不到的,如:
于是苦想,我之前是采取路径搜索的方法,即是用上下左右的方法搜索进行下一步的,这种方法上图的情况是找不到的,但是如果采用按行搜索的策略则可以实现,用深搜找到五个方格,然后用广搜来验证是否相连,于是终极一搜:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int r=3,c=4;
int toX[4]={1,0,-1,0};
int toY[4]={0,1,0,-1};
bool visA[4][5];
bool visB[4][5];
int cnt;//相连邮票数量
int len;//
struct node{
int x;
int y;
node(){};
node(int xx,int yy):x(xx),y(yy){};
};
node a[13];
bool isContinuous(int x,int y){ //是否相连
return visB[x][y];
}
bool isOut(int x,int y){
if(x<0 || x>=3 ||y<0 || y>=4) return true;
return false;
}
int bfs(){
memcpy(visB,visA,sizeof(visB));
int ct;//连通的个数
queue<node> q;
q.push(a[0]);
visB[a[0].x][a[0].y]=false;
ct=1;
node tmp;
while(!q.empty()){
tmp=q.front();q.pop();
for(int i=0; i<4; ++i){
int xx=tmp.x+toX[i];
int yy=tmp.y+toY[i];
if(!isOut(xx,yy) && isContinuous(xx,yy)){
visB[xx][yy]=false;
ct++;
q.push(node(xx,yy));
}
}
}
return ct;
}
void dfs(int row, int col, int depth ){
if(depth==5){//找到五个
if(bfs()==5) cnt++;//判断五个是否相连
return ;
}
if(row>=r) return ;
for(int i=col; i<=c; ++i){//按行搜索,注意注意!!!
if(i<c){
visA[row][i]=true;
a[len]=node(row,i);
len++;
dfs(row,i+1,depth+1);
len--;
visA[row][i]=false;
}else{//跳到下一行
dfs(row+1,0,depth);
}
}
}
int main(){
memset(visA,false,sizeof(visA));
cnt=len=0;
dfs(0,0,0);
printf("%d\n",cnt);//结果是116
return 0;
}
欢迎给予优化指导。